Xamarin.Android开发实践(十六)

原文:Xamarin.Android开发实践(十六)html

Xamarin.Android之Fragment Walkthrough

利用Fragment设计可以兼容不一样屏幕的应用

这里咱们先围观下最后的成果图,给读者打打气:android

 

普通手机上显示的结果:ide

 

在平板上显示的结果:post

 

笔者要郑重声明下,虽然看似是两种不一样的显示效果,可是同一个应用,而下面笔者将逐步教会你们如何利用Fragment制做出可以兼容不一样屏幕的应用。学习

 

准备工做

建立一个项目是必不可少的,而且Android SDK的版本要在3.0以上,建议是4.0由于笔者设定的就是4.0,新建完成以后项目会自动帮咱们建立好MainActivity,固然靠这一个还不足够,咱们还要新建一个Activity,并命名为DetailsActivity,另外还有两个Fragment分为命名为DetailsFragmentTitlesFragment,最后的目录结构应该以下图所示:url

 

 

建立兼容视图

如今咱们先把呈现部分的功能完成,咱们打开Resources\Layout下的Main.axml将下面的xml代码写入:spa

 1 <?xml version="1.0" encoding="utf-8"?>  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  3  android:orientation="horizontal"  4  android:layout_width="fill_parent"  5  android:layout_height="fill_parent">  6 <fragment  7 class="fragmentwalkthrough.TitlesFragment"  8  android:id="@+id/titles_fragment"  9  android:layout_width="fill_parent" 10  android:layout_height="fill_parent" /> 11 </LinearLayout>

这里咱们就利用了fragment做为占位符,从而显示TitlesFragment,笔者还要注意class的完整路径,要按照本身实际项目的名称来,通常都是解决方案的名字的小写加上点而后就是对应的类名了。设计

 

光有这个视图只能应付小屏幕的显示,咱们还须要为大屏幕设计一个视图。可是咱们不能在layout下继续新建,那样咱们就要用代码负责控制了,其实Android自己就已经提供了这些功能,咱们只要在Resources下新建一个文件夹而且命名为layout-large,而后在该文件夹下新建一个Main.axml,这里的视图文件命名必需要和layout下的一致,而后将下面的内容写入其中:code

 1 <?xml version="1.0" encoding="utf-8"?>  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  3  android:orientation="horizontal"  4  android:layout_width="fill_parent"  5  android:layout_height="fill_parent">  6 <fragment  7 class="fragmentwalkthrough.TitlesFragment"  8  android:id="@+id/titles_fragment"  9  android:layout_weight="1" 10  android:layout_width="0px" 11  android:layout_height="match_parent" /> 12 <FrameLayout 13 android:id="@+id/details" 14  android:layout_weight="3" 15  android:layout_width="0px" 16  android:layout_height="match_parent" /> 17 </LinearLayout>

 

 

这里多了一个FrameLayout这个就是做为内容的容器,最后咱们能够看到在咱们选择不一样的项的时候,都会在这个占位符中切换碎片(Fragment),这里提示下咱们还要把MainActivity.cs中的自动生成的代码删除,最后只要剩下如下的内容便可:xml

1         protected override void OnCreate(Bundle bundle) 2  { 3 base.OnCreate(bundle); 4  SetContentView(Resource.Layout.Main); 5 }

完成了上面的内容,咱们下面就开始从下而上来开始。

 

完善DetailsFragment

惟一须要学习的就是OnCreateView方法,这个方法就是来用指定碎片的视图的,最后显示的是返回的视图,具体的代码以下所示:

 1     public class DetailsFragment : Fragment  2  {  3 public static DetailsFragment NewInstance(int playId)  4  {  5 var detailsFrag = new DetailsFragment  6  {  7 Arguments = new Bundle()  8  };  9 detailsFrag.Arguments.PutInt("current_play_id", playId); 10 return detailsFrag; 11  } 12 13 public int ShowPlayId 14  { 15 get 16  { 17 return Arguments.GetInt("current_play_id", 0); 18  } 19  } 20 21 public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 22  { 23 if (container == null) 24  { 25 return null; 26  } 27 var scroller = new ScrollView(Activity); 28 var text = new TextView(Activity); 29 text.SetPadding(4, 4, 4, 4); 30 text.TextSize = 24; 31 text.Text = "you select " + ShowPlayId; 32  scroller.AddView(text); 33 return scroller; 34  } 35 }

咱们仅仅只是对选择的项的id保存了,提供还提供了一个快捷方法NewInstance用来实例化这个碎片,最后的内容仅仅只是经过TextView呈现的,笔者后面也能够设计一个视图,而后利用inflater参数实例化并返回。

 

 

完善DetailsActivity

这个活动纯粹只是为了兼容小屏幕的,由于它只是一个躯壳,负责将发送给它的参数在转发给DetailsFragment,并显示DetailFragment。具体的代码以下所示:

 1     [Activity(Label = "DetailsActivity")]  2 public class DetailsActivity : Activity  3  {  4 protected override void OnCreate(Bundle bundle)  5  {  6 base.OnCreate(bundle);  7 var index = Intent.Extras.GetInt("current_play_id", 0);  8 var details = DetailsFragment.NewInstance(index);  9 var ft = FragmentManager.BeginTransaction(); 10  ft.Add(Android.Resource.Id.Content, details); 11  ft.Commit(); 12  } 13 }

咱们注意到了FragmentManger这个类,它对于咱们从此使用碎片都是很是重要的,只要在活动里面切换碎片,删除碎片等都要经过它。这一过程还必需要使用BeginTransaction先开启事务,完成操做后还要经过Commit提交,不然是没有效果的。

 

 

完善TitlesFragment

这里咱们看到了列表显示的数据,而这些数据都是定义在Strings.xml中的,因此咱们先要定义这些资源,代码以下所示:

 1 <?xml version="1.0" encoding="utf-8"?>  2 <resources>  3 <string name="Hello">Hello World, Click Me!</string>  4 <string name="ApplicationName">FragmentWalkthrough</string>  5 <string-array name="TitleList">  6 <item>First</item>  7 <item>Second</item>  8 <item>Third</item>  9 <item>Fourth</item> 10 <item>Fifth</item> 11 <item>Sixth</item> 12 </string-array> 13 </resources>

完成上面的操做后,咱们就要重点学习TitlesFragment中的功能,首先咱们删除里面默认重写的方法,而后将继承的类改为ListFragment,并重写OnActivityCreated,由于咱们继承了这个类,就跟ListActivity同样,因此不须要在设置界面。

 

为了可以兼容不一样的屏幕,因此咱们须要一个bool类型的变量去保存当前的屏幕是属于大仍是小,从而决定相关的功能,而且还要有一个int类型的变量保存当前所选的数据的id,而后咱们就能够完善OnActivityCreated方法了:

 1         protected int _currentPlayId;  2 protected bool _isDualPanel;  3  4 public override void OnActivityCreated(Bundle savedInstanceState)  5  {  6 base.OnActivityCreated(savedInstanceState);  7 //从Resources将资源取出  8 string[] strarray = Resources.GetStringArray(Resource.Array.TitleList);  9 10 //实例化一个适配器并将适配器赋给ListAdapter 11 var adapter = new ArrayAdapter<string>(Activity, Android.Resource.Layout.SimpleListItemChecked, strarray); 12 ListAdapter = adapter; 13 14 //判断是否存在上一次会话的数据 15 if (savedInstanceState != null) 16  { 17 _currentPlayId = savedInstanceState.GetInt("current_play_id", 0); 18  } 19 20 //获取用于碎片的占位符 21 var detailsFrame = Activity.FindViewById<View>(Resource.Id.details); 22 23 //根据该占位符是否存在以及是否可见,从而决定是否为大屏幕 24 _isDualPanel = detailsFrame != null && detailsFrame.Visibility == ViewStates.Visible; 25 26 //当前屏幕为大屏幕时操做 27 if (_isDualPanel) 28  { 29 ListView.ChoiceMode = ChoiceMode.Single; 30  ShowDetails(_currentPlayId); 31  } 32 }

这里只是初始化了列表并判断了当前属于那种状况,下面咱们就要介绍重要的ShowDetails方法,该方法将负责用户点击某项后采用那种方式呈现,下面是该代码:

 1         public void ShowDetails(int playid)  2  {  3 _currentPlayId = playid;  4 //判断当前屏幕显示的方案  5 if (_isDualPanel)  6  {  7 //为大屏幕时显示的方案  8  9 ListView.SetItemChecked(playid, true); 10 //经过碎片管理器查找对应的碎片 若是是第一次显示则返回的是null 11 var details = FragmentManager.FindFragmentById(Resource.Id.details) as DetailsFragment; 12 13 //判断是否存在该碎片的实例化对象或该对象显示的内容是否跟当前选择的内容一致 14 if (details == null || details.ShowPlayId != playid) 15  { 16 //实例化碎片 17 details = DetailsFragment.NewInstance(playid); 18 var ft = FragmentManager.BeginTransaction(); 19 //将FrameLayout占位符替换成details碎片 20  ft.Replace(Resource.Id.details, details); 21  ft.Commit(); 22  } 23  } 24 else 25  { 26 //为小屏幕时显示的方案 27 var intent = new Intent(); 28 intent.SetClass(Activity, typeof(DetailsActivity)); 29 intent.PutExtra("current_play_id", playid); 30  StartActivity(intent); 31  } 32 }

 

这面的代码咱们经过其中的注释就能够清楚的明白了,固然咱们还要重写ListFragment的事件,代码以下所示:

1         //监听选择事件,在每次选择后从新显示详细内容 2 public override void OnListItemClick(ListView l, View v, int position, long id) 3  { 4  ShowDetails(position); 5 }

 

至此咱们就实现了可以在不一样屏幕下显示不一样界面的方式,这在很大的程度上能够复用代码,而不须要非要单独去定制专门的应用。

相关文章
相关标签/搜索