1、准备环境
对模拟器,只要“Ctrl+F12“,就可以可以实现竖屏(portrait)和横屏(landscape)的切换。
2、UI的屏幕切换实现
下面一个简单的例子,如图。
我们需要写两个Android XML文件,假定文件为chapter_19_test1.xml,放在常规目录位置layout/内容如下:
-
<?xmlversion="1.0"encoding="utf-8"?>
-
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
-
android:orientation="vertical"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent">
-
<Buttonandroid:id="@+id/c19_pick"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:layout_weight="1"
-
android:text="Pick"
-
android:enabled="true"/>
-
<Buttonandroid:id="@+id/c19_view"
-
android:layout_width="fill_parent"
-
android:layout_height="fill_parent"
-
android:layout_weight="1"
-
android:text="View"
-
android:enabled="false"/>
-
</LinearLayout>
另一个位于layout-land/目录下面,文件名称一样,这里是landsapce的排版,简单地,我们只作少许改动,将LinearLayout中的android:orientation="vertical",修改为android:orientation="horizontal",这样就可以了。
3、切换中出现什么事情
Is it so easy?在Android,关于layout widget,系统会根据你的xml文件自动进行屏幕旋转,选择正确的xml文件来进行布局。很智能吧?是的,但是仅此而已。我们做个实验:在上面xml的基础上,每按一次pick按钮,计数器testNum就加一,为了直观简单,testNum的值通过System.out打印处理,并在Button上直接显示。测试代码如下:
-
publicclassChapter19Test1extendsActivity{
-
privateinttestNum=0;
-
-
@Override
-
protectedvoidonCreate(BundlesavedInstanceState){
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.chapter_19_test1);
-
-
ButtonpickButton=(Button)findViewById(R.id.c19_pick);
-
pickButton.setText("Pick:"+testNum);
-
-
pickButton.setOnClickListener(newView.OnClickListener(){
-
-
publicvoidonClick(Viewv){
-
testNum++;
-
System.out.println("Pick:"+testNum);
-
((Button)v).setText("Pick:"+testNum);
-
}
-
});
-
-
viewButton.setEnabled(contact!=null);
-
}
-
-
}
我们在竖屏的情况下按pick的按键,三次后,然后通过"ctrl+F12"从竖屏转为横屏,再按,发现testNum没有按照与其,继续计数,而是重新开始计算,而我们希望的是能保留原来的状。在屏幕的切换中Android会destroy并re-create我们的activity。这就意味这你需要保存你的数据并且在切换的时候从保存的数据中恢复状态。
4、保存数据
我们使用onSaveInstanceState()来进行数据保存,由于是re-create,在屏幕转换时会触发onCreate(),也可以在onRestoreInstanceState()中对数据进行恢复。
-
protectedvoidonCreate(BundlesavedInstanceState){
-
......
-
ButtonpickButton=(Button)findViewById(R.id.c19_pick);
-
-
if(savedInstanceState!=null){
-
testNum=savedInstanceState.getInt("count");
-
}
-
pickButton.setText("Pick:"+testNum);
-
-
pickButton.setOnClickListener(newView.OnClickListener(){
-
......
-
});
-
}
-
-
@Override
-
-
protectedvoidonSaveInstanceState(BundleoutState){
-
-
super.onSaveInstanceState(outState);
-
outState.putInt("count",testNum);
-
}
5、稍有趣一点的例子
在上面的例子中,我们按pick按钮,采用Intent方式进入contact列表,在列表中选择某个contact,并返回。通过startActivityForResult的调用方式,我们可以获得返回值。按View按钮,这可以显示该contact的详细信息。在这个例子中,我们学习下面的几个内容:
1)如何调用contact列表new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);,如何调用查看某个contact的详细内容new Intent(Intent.ACTION_VIEW,contact)
2)如何调用带返回的intent:startActivityForResult(intent,requestCode);
3)在横竖屏切换中,复习保存数据(contact)并恢复原来状态。值得注意的是:下面的处理并不仅仅是为了横竖屏,还包括其他的恢复,例如因为电池能源太低而造成的activity的close。
-
publicclassChapter19Test1extendsActivity{
-
staticfinalintPICK_REQUEST=1000;
-
-
privateButtonviewButton=null;
-
privateUricontact=null;
-
-
protectedvoidonCreate(BundlesavedInstanceState){
-
......
-
pickButton.setOnClickListener(newView.OnClickListener(){
-
-
publicvoidonClick(Viewv){
-
Intentintent=newIntent(Intent.ACTION_PICK,ContactsContract.Contacts.CONTENT_URI);
-
startActivityForResult(intent,PICK_REQUEST);
-
}
-
});
-
-
viewButton.setOnClickListener(newView.OnClickListener(){
-
-
publicvoidonClick(Viewv){
-
startActivity(newIntent(Intent.ACTION_VIEW,contact));
-
}
-
});
-
-
restoreMe(savedInstanceState);
-
viewButton.setEnabled(contact!=null);
-
}
-
-
@Override
-
-
protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){
-
super.onActivityResult(requestCode,resultCode,data);
-
if(requestCode==PICK_REQUEST){
-
if(resultCode==RESULT_OK){
-
contact=data.getData();
-
viewButton.setEnabled(true);
-
}
-
}
-
}
-
-
@Override
-
-
protectedvoidonSaveInstanceState(BundleoutState){
-
super.onSaveInstanceState(outState);
-
if(contact!=null){
-
outState.putString("contact",contact.toString());
-
}
-
}
-
-
-
privatevoidrestoreMe(Bundlestate){
-
contact=null;
-
if(state!=null){
-
StringcontactUri=state.getString("contact");
-
if(contactUri!=null){
-
contact=Uri.parse(contactUri);
-
}
-
}
-
}
-
-
}
6、用onSaveInstanceState()保存数据的局限和替换方式
在例子中,使用了 onSaveInstanceState()来保存数据,这个调用不仅仅是在横屏竖屏的切换,同时也在其他引起中断的处理,例如低memory,因此数据保存不仅是串行进行的同时和当前之执行的进程无关。局限在于只能通过bundle来保存。
在一些activty的情况下,这样处理是没有问题,但是另一些,例如在线聊天,我们无法通过bundle将object(例如socket)保存起来,如果仅仅保存socket的信息(ip地址、端口)是没有意义的,也就是在横屏和竖屏的切换会导致连接的断开和重连接。显然不是我们期待的。
解决方法是用onRetainNonConfigurationInstance()来替代onSaveInstanceState()。用它来保存object,并通过getLastNonConfigurationInstance()来获取。这样我们可以保存socket,thread等等。上面的例子,可以修订如下:
-
publicclassChapter19Test2extendsActivity{
-
......
-
@Override
-
protectedvoidonCreate(BundlesavedInstanceState){
-
......
-
-
restoreMe();
-
......
-
}
-
-
......
-
-
@Override
-
-
publicObjectonRetainNonConfigurationInstance(){
-
returncontact;
-
}
-
-
-
privatevoidrestoreMe(){
-
contact=null;
-
if(getLastNonConfigurationInstance()!=null){
-
contact=(Uri)getLastNonConfigurationInstance();
-
}
-
}
-
}
分享到:
相关推荐
Android学习笔记(三六):横屏竖屏的切换
对模拟器,只要“Ctrl+F12“,就可以可以实现竖屏(portrait)和横屏(landscape)的切换。下面一个简单的例子,如图。我们需要写两个AndroidXML文件,假定文件为chapter_19_test1.xml,放在常规目录位置layout/内容...
Android学习笔记(三七):再谈屏幕切换
Android学习笔记(六):xml和widget
Android学习笔记(三)android studio中CheckBox自定义样式(更换复选框左侧的勾选图像) Android学习笔记(四)Android 中Activity页面的跳转及传值 Android学习笔记(五)——Toast提示、Dialog对话框、Menu菜单 ...
现代OpenGL+Qt学习笔记之二:程序框架http://blog.csdn.net/chaojiwudixiaofeixia/article/details/77917697源码。
[转载]Android学习笔记(三):Andriod程序框架
Android学习笔记 Android学习笔记 Android学习笔记
Android学习笔记
android 学习笔记(全全整理),吧android学习笔记全部整理下来了,可以去好好学习学习
而我希望平板是横屏的,来查看fragment在宽屏上的应用效果,这竖屏的平板感觉只是放大版的手机~ 本来设计的两个fragment在竖屏的平板上看都“太瘦”了,反而有些奇怪,影响学习体验。 搜索博客找解决方案,上面全都...
第一行代码 android学习笔记 修改完整版
Android学习笔记(二六):输入法
Android 学习笔记(二七):Menu
Android学习笔记(三一):线程:Message和Runnable
Android 学习笔记(十三):Activity-GridView
Android学习笔记(二):安装环境
NULL 博文链接:https://sarin.iteye.com/blog/1632124
Android学习笔记(九):Activity-RelativeLayout