(持續更新)Xamarin.Forms之常見的問題


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);
        }

 


免責聲明!

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



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