業余時間寫的一個知乎日報win10版客戶端,支持收藏,評論,點贊等。
商店地址:https://www.microsoft.com/zh-cn/store/apps/%E5%A4%A9%E5%A4%A9%E8%AF%BB%E6%8A%A5/9nblggh5fx8z。
開源地址:https://github.com/brookshi/UWP_ZhiHuRiBao 歡迎fork/star。
先上圖:
PC版:
Mobile版:
磁貼:
引用的一系列的庫:
陰影:https://github.com/brookshi/XPShadow
網絡:https://github.com/brookshi/XPHttp
列表:https://github.com/brookshi/LLMListView
內部通信:https://github.com/brookshi/LLQNotifier
按鈕:https://github.com/brookshi/XPButton
動畫:https://github.com/brookshi/LLMAnimator
新浪微博登錄:http://weibowinrtsdk.codeplex.com/
API是通過用Fiddler抓取Android版知乎日報獲得。
這個應用比較有意思的點:
1.文章顯示 |
文章api獲取的是一串html,自然想到用webview來顯示,不過打開一個文章就用一個webview,占用內存比較大。為解決這個問題,開始嘗試將html轉成xaml,用RichTextBox顯示。用的是: https://github.com/stimulant/SocialStream/blob/master/XAMLConverter/HtmlToXamlConverter.cs
可惜不能支持所有html節點,而且image顯示很慢,字體顯示怪異,效果不佳,放棄。
回到webview,既然是多個webview造成內存大,那只用一個webview不就可以了! 嗯,單例模式。
每次打開文章時把這個靜態的webview單例從Parent中移除,再加到當前Page中。
1 public static class WebViewUtil 2 { 3 static WebViewUtil() 4 { 5 _webViewInstance.ScriptNotify += async (s, e) => 6 { 7 string data = e.Value; 8 if (!string.IsNullOrEmpty(data) && data.StartsWith(Html.NotifyPrex)) 9 { 10 await Launcher.LaunchUriAsync(new Uri(data.Substring(Html.NotifyPrex.Length))); 11 } 12 }; 13 } 14 15 private readonly static object _parentLocker = new object(); 16 17 private readonly static List<Panel> _webViewParents = new List<Panel>(); 18 19 private readonly static WebView _webViewInstance = new WebView(); 20 21 public static void AddWebViewWithBinding(Panel parent, object source, string path) 22 { 23 Clear(); 24 RemoveParent(); 25 _webViewInstance.SetBinding(WebViewExtend.ContentProperty, new Binding() { Source = source, Path = new PropertyPath(path) }); 26 lock(_parentLocker) 27 { 28 parent.Children.Add(_webViewInstance); 29 if (!_webViewParents.Contains(parent)) 30 { 31 _webViewParents.Add(parent); 32 } 33 } 34 } 35 36 public static void Clear() 37 { 38 _webViewInstance.NavigateToString(""); 39 } 40 41 public static bool IsParent(Panel panel) 42 { 43 return panel.Children.Contains(_webViewInstance); 44 } 45 46 public static bool HasParent { get { return _webViewInstance.Parent is Panel; } } 47 48 public static void RemoveParent() 49 { 50 lock(_parentLocker) 51 { 52 _webViewParents.ForEach(panel => 53 { 54 if (panel.Children.Contains(_webViewInstance)) 55 panel.Children.Remove(_webViewInstance); 56 }); 57 } 58 } 59 }
2.布局 |
WinRT支持根據一些條件來顯示不同的布局,最常用的就是AdaptiveTrigger,通過設置MinWindowWidth/MinWindowHeight來顯示/隱藏元素來展示不同的布局。
<VisualState> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="{Binding Source={StaticResource Config}, Path=MinWidth_UIStatus_ListAndContent}" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="StoryContentView.IsPaneOpen" Value="false" /> <Setter Target="StoryContentView.DisplayMode" Value="Overlay" /> </VisualState.Setters> </VisualState>
但是有時候條件不單單是Width/Height,還需要其他條件來決定布局,這時可以模仿AdaptiveTrigger創建一個我們自己的StateTrigger。自定義的trigger需要繼承StateTriggerBase,加入其他條件ExtraCondition,通過SizeChanged的事件來觸發Trigger。
1 public class AdaptiveTriggerExtended : StateTriggerBase 2 { 3 public double MinWindowWidth 4 { 5 get { return (double)GetValue(MinWindowWidthProperty); } 6 set { SetValue(MinWindowWidthProperty, value); } 7 } 8 public static readonly DependencyProperty MinWindowWidthProperty = 9 DependencyProperty.Register("MinWindowWidth", typeof(double), typeof(AdaptiveTriggerExtended), new PropertyMetadata(0)); 10 11 public bool ExtraCondition 12 { 13 get { return (bool)GetValue(ExtraConditionProperty); } 14 set { SetValue(ExtraConditionProperty, value); } 15 } 16 public static readonly DependencyProperty ExtraConditionProperty = 17 DependencyProperty.Register("ExtraCondition", typeof(bool), typeof(AdaptiveTriggerExtended), new PropertyMetadata(true)); 18 19 private FrameworkElement _targetElement; 20 public FrameworkElement TargetElement 21 { 22 get { return _targetElement; } 23 set 24 { 25 _targetElement = value; 26 _targetElement.SizeChanged += (s, e) => SetActive(ExtraCondition && e.NewSize.Width >= MinWindowWidth); 27 } 28 } 29 }
3.微博登錄 |
官方知乎日報登錄肯定有自己的AppID和AppSecret,這個不太好找(其實也能找到,把android版日報反編譯,細心點就可以找到),不過發現用我自己從微博申請的也可以用。
官方推薦的win8 SDK,在win10也可以用。
4.Popup Message |
Win10里Toast是把消息發到消息中心,對應用內部提示不是很友好,這里我用Popup模擬了一下android的toast。
思路是生成一個包含TextBlock的Popup,把要彈出的消息push到一個queue里,按順序彈出消息,遇到相同的就跳過。
具體實現代碼這里就不貼了,可以參考PopupMessage.cs
其他引用的庫如陰影,按鈕,列表等就放到后面再寫。