MonoDroid学习笔记(六)—— 手机的页面转换及页面间的数据传递

做过asp.net或其他web开发的朋友都知道,想要在两个网页间做转换,只要利用超链接就可以实现。但在手机里,要如何实现手机页面之间的转换呢?最简单的方法就是改变Activity的Layout。首先准备两个布局文件Main.axml和Layout2.axml。在Layout1中放置一个按钮,当单击时,显示Layout2,同样地,在Layout2里也放一个按钮,当单击时回到Main.

[xhtml]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.                 android:layout_width="fill_parent"  
  4.                 android:layout_height="fill_parent">  
  5.   <TextView android:text="这是Layout1"  
  6.             android:layout_width="wrap_content"  
  7.             android:layout_height="wrap_content" />  
  8.   <Button android:text="跳到Layout2"  
  9.           android:layout_y="30px"  
  10.           android:layout_width="wrap_content"  
  11.           android:layout_height="wrap_content"  
  12.           android:id="@+id/btn1"/>  
  13. </AbsoluteLayout>  
 

 

[xhtml]  view plain copy print ?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.                 android:layout_width="fill_parent"  
  4.                 android:layout_height="fill_parent"  
  5.                 android:background="@color/white">  
  6.   <TextView android:text="这是Layout2"  
  7.             android:layout_width="wrap_content"  
  8.             android:layout_height="wrap_content"/>  
  9.   <Button android:text="跳到Layout1"  
  10.           android:layout_y="30px"  
  11.           android:layout_width="wrap_content"  
  12.           android:layout_height="wrap_content"  
  13.           android:id="@+id/btn2"/>  
  14. </AbsoluteLayout>  
 

然后在Activity1.cs中的OnCreate方法里加入如下代码:

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.Runtime;  
  5. using Android.Views;  
  6. using Android.Widget;  
  7. using Android.OS;  
  8. using MonoDroidTest.Tabs;  
  9. using Android.Util;  
  10. using Java.IO;  
  11. using Android.Database;  
  12. namespace MonoDroidTest  
  13. {  
  14.     [Activity(Label = "MonoDroidTest", MainLauncher = true)]  
  15.     public class Activity1 : Activity  
  16.     {  
  17.         protected override void OnCreate(Bundle bundle)  
  18.         {  
  19.             base.OnCreate(bundle);  
  20.             SetContentView(Resource.Layout.Main);  
  21.             Button btn1 = FindViewById<Button>(Resource.Id.btn1);  
  22.             btn1.Click += (sender, e) =>   
  23.             {  
  24.                 this.SetContentView(Resource.Layout.Activity2);  
  25.                 Button btn2 = FindViewById<Button>(Resource.Id.btn2);  
  26.                 btn2.Click += (sender2, e2) =>   
  27.                 {  
  28.                     OnCreate(bundle);  
  29.                 };  
  30.             };  
  31.         }  
  32.     }  
  33. }  
 

运用改变Activity的Layout这个技巧,就可以做出手机页面转换的效果,当然也可以搭配之前介绍的Style设置,进行更加灵活的布局配置运用。再者,利用SetContentView来置换页面还有一个特别的优点,即所有程序里的变量皆存在相同的状态,无论是类成员、类方法等,都在一个Activity的状态中直接取得,并没有参数传递的问题。比如要进行分步导航的页面,从第一个页面得到的信息无需传递到第二个页面,而是一直存放在当前Activity的成员中,可以随时拿来使用。

 

如果要转换的页面不单只是背景,颜色或文字的内容的不同,而是Activity的置换,那就不是单单改变Layout就能完成的了。尤其是需要传递的数据不像网页可以通过Session或Cache来实现,在程序里移交主控权到另一个Activity,光靠先前的Layout技巧是办不到的。

那要如何解决Activity控制权的移交呢?在MonoDroid里,可以在主程序中使用StartActivity方法来调用另一个Activity(主程序本身就是一个Activity),但当中的关键并不在StartActivity这个方法,而是Intent这个特有的对象。Intent就如同其英文字义,是“想要”或“意图”之意,在主Activity中,告诉程序自己是什么,并想要前往哪里,这就是Intent对象所处理的事情了。

布局文件与刚才一样,不同的是程序代码,修改Activity.cs如下,在这里教大家另外一个绑定控件事件的方法,在.net程序里,我们要绑定事件,只要在事件名后+=事件处理对象或lambda表达式即可,如btn.Click += (sender, e) => { };在MonoDroid里,为了与Java中的写法保持一致,除了上面这种方式之外,还提供了另外一种方式,即SetOnXXXListener方法。如按钮的Click事件,就调用SetOnClickListener,传入的参数是实现View.IOnClickListener的类。另外,要实现Java中的借口,你的类还要继承Java.Lang.Object类,这样就无需实现IObject的Handle属性了。

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.Runtime;  
  5. using Android.Views;  
  6. using Android.Widget;  
  7. using Android.OS;  
  8. using MonoDroidTest.Tabs;  
  9. using Android.Util;  
  10. using Java.IO;  
  11. using Android.Database;  
  12. namespace MonoDroidTest  
  13. {  
  14.     [Activity(Label = "MonoDroidTest", MainLauncher = true)]  
  15.     public class Activity1 : Activity  
  16.     {  
  17.         protected override void OnCreate(Bundle bundle)  
  18.         {  
  19.             base.OnCreate(bundle);  
  20.             SetContentView(Resource.Layout.Main);  
  21.             Button btn = FindViewById<Button>(Resource.Id.btn1);  
  22.             btn.SetOnClickListener(new ClickListener());  
  23.         }  
  24.     }  
  25.     public class ClickListener : Java.Lang.Object, View.IOnClickListener  
  26.     {  
  27.         public void OnClick(View v)  
  28.         {  
  29.             Activity act = v.Context as Activity;  
  30.             Intent intent = new Intent();  
  31.             intent.SetClass(act, typeof(Activity2));  
  32.             act.StartActivity(intent);  
  33.             act.Finish();  
  34.         }  
  35.     }  
  36. }  
 

 

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Android.App;  
  6. using Android.Content;  
  7. using Android.OS;  
  8. using Android.Runtime;  
  9. using Android.Views;  
  10. using Android.Widget;  
  11. namespace MonoDroidTest  
  12. {  
  13.     [Activity(Label = "My Activity")]  
  14.     public class Activity2 : Activity  
  15.     {  
  16.         protected override void OnCreate(Bundle bundle)  
  17.         {  
  18.             base.OnCreate(bundle);  
  19.             SetContentView(Resource.Layout.Activity2);  
  20.             Button btn = FindViewById<Button>(Resource.Id.btn2);  
  21.             btn.Click += delegate  
  22.             {  
  23.                 Intent intent = new Intent();  
  24.                 intent.SetClass(thistypeof(Activity1));  
  25.                 this.StartActivity(intent);  
  26.                 this.Finish();  
  27.             };  
  28.         }  
  29.     }  
  30. }  
 

 

在Activity1和Activity2两个类里都调用了Finish()这个方法,它代表这个Activity已经运作完毕,当系统接收到这个命令时,即会关闭此Activity,所以此时单击模拟器的返回(Back)键,并不会回到上一个Activity的画面,如果要让模拟器的返回键有回上一页的效果,可以将此行代码注释掉。同理,在两个Acitivity在切换时,并非真的只有两个Activity在切换,而是在单击按钮时再重新调用一个新的Activity。

 

若需要在调用另一个Activity的同时传递数据,那么就需要利用Bundle对象来封装数据了。将想要传递的数据或参数通过Bundle来传递不同Intent之间的数据。

我们从Activity1调用Activity2的同时,把一个字符串和一个整型传到Activity2试试,对ClickListener类的OnClick方法增加几行代码:

[c-sharp]  view plain copy print ?
  1. public void OnClick(View v)  
  2. {  
  3.     Activity act = v.Context as Activity;  
  4.     Intent intent = new Intent();  
  5.     intent.SetClass(act, typeof(Activity2));  
  6.     Bundle b = new Bundle();  
  7.     b.PutString("name""ojlovecd");  
  8.     b.PutInt("score", 76195);  
  9.     intent.PutExtras(b);  
  10.     act.StartActivity(intent);  
  11.     act.Finish();  
  12. }  
 

然后在Activity2中进行接收这两个值,为了在Activity2加载后弹出提示,我们先来封装一个信息框提示类。这里要用到AlertDialog窗口,它常用于“程序提示”,“警告”或“确认”等。

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. namespace MonoDroidTest  
  5. {  
  6.     public class MessageBox  
  7.     {  
  8.         public static void Show(Context ctx,string title, string message)  
  9.         {  
  10.             AlertDialog.Builder dlg = new AlertDialog.Builder(ctx);  
  11.             dlg.SetTitle(title);  
  12.             dlg.SetMessage(message);  
  13.             dlg.SetPositiveButton("确定"delegate { });  
  14.             dlg.Show();  
  15.         }  
  16.         public static void ShowErrorMessage(Context ctx, Exception ex)  
  17.         {  
  18.             Show(ctx, "错误", ex.Message);  
  19.         }  
  20.     }  
  21. }  
 

然后我们再在Activity2中使用这个类来显示从Activity1传递过来的参数:

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Android.App;  
  6. using Android.Content;  
  7. using Android.OS;  
  8. using Android.Runtime;  
  9. using Android.Views;  
  10. using Android.Widget;  
  11. namespace MonoDroidTest  
  12. {  
  13.     [Activity(Label = "My Activity")]  
  14.     public class Activity2 : Activity  
  15.     {  
  16.         protected override void OnCreate(Bundle bundle)  
  17.         {  
  18.             base.OnCreate(bundle);  
  19.             SetContentView(Resource.Layout.Activity2);  
  20.             Bundle b = this.Intent.Extras;  
  21.             Button btn = FindViewById<Button>(Resource.Id.btn2);  
  22.             btn.Click += delegate  
  23.             {  
  24.                 Intent intent = new Intent();  
  25.                 intent.SetClass(thistypeof(Activity1));  
  26.                 this.StartActivity(intent);  
  27.                 this.Finish();  
  28.             };  
  29.             MessageBox.Show(this"信息"string.Format("用户名:{0}/n积分:{1}", b.GetString("name"), b.GetInt("score")));  
  30.         }  
  31.     }  
  32. }  
 

运行结果:

MonoDroid学习笔记(六)—— 手机的页面转换及页面间的数据传递

Bundle对象针对不同的数据类型提供了多种方法,例如上面传递string类型的数据,使用了PutString,而要传递double类型的数据,使用PutDouble,反之,要从Bundle对象取出数据,就把Put改为Get即可。我曾经尝试传递非基础类型的数据,即自定义类型的数据,但无论我的对象是实现了Java.IO.ISerializable,然后调用PutSerializable方法,还是实现IParcelable,调用PutParcelable方法,在Get的时候都会报错,实在无奈,如果有哪位朋友能够成功传递自定义类型的数据的话,还请共享一下。

 

在上一个范例中,好不容易将数据从Activity1传递到Activity2,如果要再回到Activity1,数据该不会要再封装一次吧?而且前一个Activity1早就被destroy了,倘若在Activity1最后以Finish()结束程序,再通过Activity2将数据采用Bundle的方式通过新打开Activity1传递参数,这样的做法虽然也可以恢复用户输入的数据,但并不符合我们的期待,尤其是用户曾经输入过的数据,如果不小心单击回到上一页,数据就消失不见了。

如果要在第二个页面加上一个“回上页”的按钮,而非通过模拟器的返回键,且回上页后又能保留之前的相关信息,那么就必须用StartActivityForResult方法来唤起另一个Activity。要处理Activity2返回的结果,就要在Activity1中重写OnActivityResult方法,程序如下:

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using Android.App;  
  3. using Android.Content;  
  4. using Android.Runtime;  
  5. using Android.Views;  
  6. using Android.Widget;  
  7. using Android.OS;  
  8. using MonoDroidTest.Tabs;  
  9. using Android.Util;  
  10. using Java.IO;  
  11. using Android.Database;  
  12. namespace MonoDroidTest  
  13. {  
  14.     [Activity(Label = "MonoDroidTest", MainLauncher = true)]  
  15.     public class Activity1 : Activity  
  16.     {  
  17.         protected override void OnCreate(Bundle bundle)  
  18.         {  
  19.             base.OnCreate(bundle);  
  20.             SetContentView(Resource.Layout.Main);  
  21.             Button btn = FindViewById<Button>(Resource.Id.btn1);  
  22.             btn.SetOnClickListener(new ClickListener());  
  23.         }  
  24.   
  25.         protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)  
  26.         {  
  27.             if (resultCode == Result.Ok)  
  28.             {  
  29.                 Bundle b = data.Extras;  
  30.                 string name = b.GetString("name");  
  31.                 int score = b.GetInt("score");  
  32.                 string blogUrl = b.GetString("blogUrl");  
  33.                 int availableScore = b.GetInt("availableScore");  
  34.                 MessageBox.Show(this"提示"string.Format("名称:{0}/n积分:{1}/n博客地址:{2}/n可用分:{3}", name, score, blogUrl, availableScore));  
  35.             }  
  36.         }  
  37.     }  
  38.     public class ClickListener : Java.Lang.Object, View.IOnClickListener  
  39.     {  
  40.         public void OnClick(View v)  
  41.         {  
  42.             //try  
  43.             //{  
  44.             Activity act = v.Context as Activity;  
  45.             Intent intent = new Intent();  
  46.             intent.SetClass(act, typeof(Activity2));  
  47.             Bundle b = new Bundle();  
  48.             b.PutString("name""ojlovecd");  
  49.             b.PutInt("score", 76195);  
  50.             intent.PutExtras(b);  
  51.             act.StartActivityForResult(intent, 0);  
  52.             //act.StartActivity(intent);  
  53.             //act.Finish();  
  54.             //}  
  55.             //catch (Exception ex)  
  56.             //{  
  57.             //    MessageBox.Show(v.Context, "错误", ex.Message);  
  58.             //}  
  59.         }  
  60.     }  
  61. }  
 

 

[c-sharp]  view plain copy print ?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using Android.App;  
  6. using Android.Content;  
  7. using Android.OS;  
  8. using Android.Runtime;  
  9. using Android.Views;  
  10. using Android.Widget;  
  11. namespace MonoDroidTest  
  12. {  
  13.     [Activity(Label = "My Activity")]  
  14.     public class Activity2 : Activity  
  15.     {  
  16.         protected override void OnCreate(Bundle bundle)  
  17.         {  
  18.             base.OnCreate(bundle);  
  19.             SetContentView(Resource.Layout.Activity2);  
  20.             Bundle b = this.Intent.Extras;  
  21.             // Create your application here  
  22.             Button btn = FindViewById<Button>(Resource.Id.btn2);  
  23.             btn.Click += delegate  
  24.             {  
  25.                 Intent intent = new Intent();  
  26.                 b.PutString("blogUrl""http://blog.csdn.net/ojlovecd");  
  27.                 b.PutInt("availableScore", 18734);  
  28.                 intent.PutExtras(b);  
  29.                 this.SetResult(Result.Ok, intent);  
  30.                 this.Finish();  
  31.             };  
  32.             MessageBox.Show(this"信息"string.Format("用户名:{0}/n积分:{1}", b.GetString("name"), b.GetInt("score")));  
  33.         }  
  34.     }  
  35. }  
 

 

运行结果:

MonoDroid学习笔记(六)—— 手机的页面转换及页面间的数据传递

就本范例而言,其实使用StartActivity也可以达成相同的效果,仅需在Activity1被Create时判断Intent内有没有数据,有的话,就将数据带入,没有就带入null。但程序还需要做有无值的比较,较为繁琐,既然MonoDroid API提供了更好用的方法,何乐而不为呢?更何况如果系统不是只有几行,而是几百几千行,那不就头大了?

转载http://blog.csdn.net/ojlovecd/article/details/6302307

你可能感兴趣的:(学习笔记)