1.如果根據用戶的登錄情況來動態的設置MainPage
如果本地有用戶的信息,則直接登錄到主界面MainPage
如果沒有,則需要進入到LoginPage,並且登錄成功后進入MainPage,並且移除LoginPage,否則會出現按返回鍵重新右MainPage進入LoginPage的情況,顯然這不符合常規
App.xaml.cs:
protected static Page GetMainPage()
{
Page mainPage = null;
if (AppParams.IsLogin) {
mainPage = new MainPage ();
} else {
mainPage = new LoginPage ();
}
return mainPage;
}
LoginPage.xaml.cs:
App.Current.MainPage.Navigation.PopModalAsync(); App.Current.MainPage=new MainPage();
MainPage是一個MasterDetailPage,是將Detail設置為Detail=new NavigationPage(new DetailPage);
如果你的主頁是一個常規的Contentpage,此時上面的第二段話應該是:
App.Current.MainPage.Navigation.PopModalAsync(); App.Current.MainPage=new NavigationPage(new MainPage());
當然,你如果不需要Navigation,當然可以不用這樣寫了
2.主線程與異步線程注意的地方
今天發現一個很奇怪的問題,本來就下面這段代碼在主線程中執行,為了加快速度,將之移到異步線程,然后發現功能不對了
var curPage = FormsCommonUtils.GetCurrentPage (); if (curPage != null&&curPage.ToolbarItems!=null) { for (int i=0;i<curPage.ToolbarItems.Count;i++) { if (curPage.ToolbarItems[i].Text == Strings.ToolbarItem_CacheList) { //不能放在非主線程中執行,執行的時候,i已經又++了,此時並不會移除item Device.BeginInvokeOnMainThread (()=>{ try { curPage.ToolbarItems.RemoveAt(i); } catch (Exception ex) { } }); } }
就是移除ToolbarItem,發現放在異步線程中時,
curPage.ToolbarItems.RemoveAt(i); //i=3
說明執行這段代碼的時候,i又在后面判斷了一次
結論:涉及到for循環的時候,要將整個for循環放在主線程中執行,不要單獨將{}里面的代碼放在主線程中執行
3.最蛋疼的控件Picker
Picker可謂forms里面最垃圾的一個控件,本來可以做成數據綁定的,第三方都實現了,官方就是沒有實現
今天又遇到一個問題,我通過雙向綁定Picker的SelectedIndex來改變Picker的選中狀態,發現這個改變在構造函數中是無效的,ViewAppearing中才有效,譬如你在構造函數中設置了Picker的SelectedIndex為1(此時已給Picker設置了Items),最后實際的效果還是初始狀態:
猜想一:
設置Picker的Items這個過程需要花費時間,你在復制SelectedIndex為1的時候,Items的設置還沒完成
猜想二:
待添加...
Picker為我自定義可綁定的BoundPicker,原生的測試的確可以,不會發生上面:
for (int i = 0; i < 5; i++) { myPicker.Items.Add (i+""); } myPicker.SelectedIndex = 2;
4.禁用Page里面的所有控件
1.實際測試不管是設置Page,獲取Page.Content第一級元素的IsEnable為false都是沒有效果的,布局里面的控件依舊有效
2.想用Style來設置所有元素的IsEnabled屬性,發現Style的TargetType不支持繼承類型的,譬如你設置TargteType=View,並不會改變所有控件的屬性(所有控件都是繼承子View),所以如果想到Style來完成,必須搞清楚Page里面到底有哪些種類的控件,然后針對這個種類的逐個添加Style
3.最簡單的方法,如果主布局是一個RelativeLayout或者Grid,可以在最上面添加一個透明的布局,這樣就完全屏蔽了下面的控件
4.像Android那樣,從Page的對象樹,依次向下找到所有的控件,每個控件逐一設置
5.Binding遇到的奇怪的問題
其它不重要,重要的是這坑爹的問題沒有報錯,直接就退出了,什么日志都沒有
<Entry Grid.Row="3" Grid.Column="1" Text="{Binding inputunitname}" />
private string _inputunitname; /// <summary> /// /// </summary> public string inputunitname{ get{ return _inputunitname;} set{ SetProperty (ref _inputunitname, value);} }
直接賦值對象,inputunitname為對象里面的一個屬性,如果這樣寫,直接退出,不是FC,什么錯誤都沒有
所以,如果大家只是使用Entry顯示數據的時候,注意設置BindingMode為OneWay,不要設置NotifyPropertyChanged(""),可能就會碰到我這個問題,還是修改xaml多次試出來問題的根源的
好吧,實際上model里面還有其它的數據也是跟inputunitname一樣的格式,但是就是不報錯,算我倒霉,犯了忌諱了
6.Converter不觸發
Title="{Binding DataList.Count,Converter={StaticResource ListCountTitleConverter},ConverterParameter='巡檢任務'}"
這種情況,如果DataList==null時,Converter是不會被觸發的,最好是將Path設為DataList而不是DataList.Count
7.像View和Control這種出現無法識別
因為在Xaml文件中的class里面,有View作為命名空間,與類沖突了,將命名空間不使用View就行了
8.StringFormat導致的卡死的問題
Forms版本:2.3.1
當傳過去的Value為null的時候,此時設置了StringFormat,會導致界面卡死,譬如{Binding value,StringFormat='{0}米'}
這種情況會在Entry中出現,Entry的默認值是TwoWay,如果設置Mode=OneWay,該現象會消失
9.StackLayout中前面元素的高度與后面元素的高度一致
10.左右靠邊對其
這個一個很簡單的問題,但是有時候在某些特定情況下,會出現一些情況
<StackLayout Orientation="Horizontal" Grid.Row="4" Grid.ColumnSpan="3" > <Label Text="11344asdasdasdasdsadsadsadsaddsd" LineBreakMode="TailTruncation" TextColor="Red" HorizontalOptions="StartAndExpand"/> <Label Grid.Column="1" Text="右邊" TextColor="Green"/> </StackLayout>
//如果左邊的文字比較短,一切是沒問題的
//但是如果左邊的問題過長,會將右邊的問題換行,或者向左移動
那將右邊的Label的LineBreakMode設為NoWrap,是不是會解決這種情況呢?
//依舊不會,會直接將Label擠出屏幕
正確的方法:
<Grid Orientation="Horizontal" Grid.Row="3" Grid.ColumnSpan="3"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Label Text="11344asdasdasdasdsadsadsadsaddsdsddsdsdsdsddsdsada" LineBreakMode="TailTruncation" TextColor="Red" HorizontalOptions="StartAndExpand"/> <Label Grid.Column="1" Text="右邊" TextColor="Green"/> </Grid>
//即使左邊的文字過長,也不會出現上面的情況
11.webView支持手勢放大縮小
iOS: public class CustomWebViewRenderer : WebViewRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); var view = (UIWebView)NativeView; view.ScrollView.ScrollEnabled = true; view.ScalesPageToFit = true; } } Android: protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e) { base.OnElementChanged(e); var settings = Control.Settings; settings.JavaScriptEnabled = true; settings.BuiltInZoomControls = true; settings.UseWideViewPort = true; settings.SetSupportZoom(true); }
