知乎日報win10版 - 天天讀報【開源】


業余時間寫的一個知乎日報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

   

其他引用的庫如陰影,按鈕,列表等就放到后面再寫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM