zoukankan      html  css  js  c++  java
  • (持续更新)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);
            }
  • 相关阅读:
    图标工具箱
    第40课 程序的内存布局
    第39课 程序中的三国天下
    第38课 动态内存分配
    第37课 指针阅读技巧分析
    第36课 函数与指针分析
    第35课 数组参数和指针参数分析
    第34课 多维数组和多维指针
    第33课 main函数与命令行参数
    第32课 数组指针和指针数组分析
  • 原文地址:https://www.cnblogs.com/yz1311/p/5233287.html
Copyright © 2011-2022 走看看