很多应用都会根据设备的横竖屏状态,呈现不同的界面。为的是在不同屏幕长宽的情况下,合理的利用屏幕空间,让用户获得体验上的最佳。
这一节,我们将给计算器添加横屏的布局界面。
添加横屏布局的原理很简单,
res
目录下增加layout-land
目录;activity_main.xml
的布局文件;activity_main.xml
中实现;onCreate()
函数会被重新调用,setContentView()
函数此时加载的布局文件,就是res\layout-land\activity_main.xml
;通过观察我们可以发现横屏界面和竖屏界面在很多地方都是有相似的。图中相同的色块都比较相似,如果能提取出来重复使用就好了。
为了使横竖界面的布局模块能够抽取出来,保持一致。我们首先要对竖屏界面的布局方式作出修改,让它变成像色块分区那样的结构。这里只需要调整键盘区域,修改activity_main.xml
文件,让其布局结构按如下方案修改:
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2">
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:orientation="vertical">
<!--这里将C DEL /按钮和数字键按照上下排列,将原来的TableLayout分成上下两个部分-->
<!--这里是C DEL /按钮区域,还是使用LinearLayout-->
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1">
......
</LinearLayout>
<!--这里是数字键盘区域,还是使用TableLayout-->
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="4">
......
</TableLayout>
......
</LinearLayout>
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1">
<!--这里放* - + =符号,不用改变-->
......
</LinearLayout>
/*******************************************************************/
* 版权声明
* 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。
/*******************************************************************/
Android SDK为我们提供了和两种标签,方便开发者在布局文件中重复利用相同的布局。
res\layout
目录下创建display_area.xml
;将显示区域的布局放到新建的xml文件当中,最外层使用merge
标签;
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/result_area" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" style="@style/TextAreaStyle" />
<View android:layout_width="match_parent" android:layout_height="5dp" android:background="@color/colorDisplayDivider" />
<TextView android:id="@+id/formula_area" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" style="@style/TextAreaStyle" />
</merge>
替换res\layout\activity_main.xml
中显示区域的布局为<include>
标签;<include>
标签的layout
属性用来制定要包含的其他布局,这里要使用@layout/
进行引用。
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical">
<include layout="@layout/display_area"/>
</LinearLayout>
0~9
和.
res\layout
目录下创建digital_btn_area.xml
;将TableLayout
中的布局放到新建的xml文件当中,最外层使用merge
标签;
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_7" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_7" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_8" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_8" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_9" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_9" style="@style/DigitalBtnStyle" />
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_4" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_4" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_5" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_5" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_6" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_6" style="@style/DigitalBtnStyle" />
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_1" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_1" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_2" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_2" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_3" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_3" style="@style/DigitalBtnStyle" />
</TableRow>
<TableRow android:layout_weight="1">
<Button android:id="@+id/btn_0" android:onClick="onClick" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_0" style="@style/DigitalBtnStyle" />
<Button android:id="@+id/btn_dot" android:onClick="onClick" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" android:text="@string/btn_dot" style="@style/DigitalBtnStyle" />
</TableRow>
</merge>
替换res\layout\activity_main.xml
中的对应区域的布局为<include>
标签;
<TableLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="4">
<include layout="@layout/digital_btn_area"/>
</TableLayout>
C
DEL
和/
res\layout
目录下创建symbol_light_btn_area.xml
;LinearLayout
中的布局放到新建的xml文件当中,最外层使用merge
标签;需要注意的是,这里要把android:layout_width
和android:layout_height
都设置成match_parent
,为的是在横屏的时候,这部分按钮也可以被平均分配;
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:id="@+id/btn_c" android:onClick="onClick" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/btn_c" style="@style/SymbolLightBtnStyle" />
<Button android:id="@+id/btn_del" android:onClick="onClick" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/btn_del" style="@style/SymbolLightBtnStyle" />
<Button android:id="@+id/btn_div" android:onClick="onClick" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/btn_div" style="@style/SymbolLightBtnStyle" />
</merge>
在res\layout\activity_main.xml
中的对应区域,使用<include>
标签;
<LinearLayout android:layout_weight="1" android:layout_height="0dp" android:layout_width="match_parent">
<include layout="@layout/symbol_light_btn_area"/>
</LinearLayout>
*
-
+
和=
res\layout
目录下创建symbol_dark_btn_area.xml
;将深色符号区域LinearLayout
中的布局放到新建的xml文件当中,最外层使用merge
标签;
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:id="@+id/btn_mul" android:onClick="onClick" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/btn_mul" style="@style/SymbolDarkBtnStyle" />
<Button android:id="@+id/btn_sub" android:onClick="onClick" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/btn_sub" style="@style/SymbolDarkBtnStyle" />
<Button android:id="@+id/btn_add" android:onClick="onClick" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/btn_add" style="@style/SymbolDarkBtnStyle" />
<Button android:id="@+id/btn_equ" android:layout_weight="2" android:layout_width="match_parent" android:layout_height="0dp" android:text="@string/btn_equ" android:onClick="onClick" style="@style/SymbolDarkBtnStyle" />
</merge>
在res\layout\activity_main.xml
中的对应区域,使用<include>
标签;
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical">
<include layout="@layout/symbol_dark_btn_area"/>
</LinearLayout>
按照横屏的设计创建横屏布局文件。
在项目浏览框
,找到res目录
,点击右键,选择new
->android resource file
;
在对应栏位按照下图填写;
布局方向,选择landscape
;这样Android Studio就会在在res
目录下增加layout-land
目录;并在此目录下增加一个名字为activity_main.xml
的布局文件;
修改新创建的布局文件为,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.anddle.calculator.MainActivity" android:background="@color/colorAppBG">
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:orientation="vertical">
<include layout="@layout/display_area"/>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3">
<TableLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3">
<include layout="@layout/digital_btn_area"/>
</TableLayout>
<LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="vertical">
<include layout="@layout/symbol_dark_btn_area"/>
</LinearLayout>
<LinearLayout android:layout_weight="1" android:layout_height="match_parent" android:layout_width="0dp" android:orientation="vertical">
<include layout="@layout/symbol_light_btn_area"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
重新运行程序到设备上,并选择设备,就会发现计算器的界面会根据设备横竖状态的不同而自己切换了。
虽然计算器的横竖屏会自动切换界面了,但是我们会发现一个问题:当在竖屏界面输入计算表达式以后,旋转设备,表达式区域会被清空。
所以需要我们增加一个功能,让设备旋转的时候,数据不会被清除掉。
Activity由Android SDK开发框架提供给我们使用。它帮助我们完成了很多应用界面启动后需要进行的操作。当我们需要在这些操作中添加自己希望的逻辑时,就可以通过继承覆盖这些方法,覆盖时加上自己的代码,例如Activity的:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onRestart() {
super.onRestart();
}
这也就是使用框架进行开发的优势。
在Activity众多的方法当中,onSaveInstanceState()
和onRestoreInstanceState()
提供了一个Activity被系统自动销毁时,进行处理的机会。
Activity一般是在用户点击返回
按钮后被销毁的,但是有的时候也会被操作系统自动销毁,
onSaveInstanceState()
会在Activity被切换到后台的时候被调用,我们就应该在这里添加上保存数据的逻辑。
如果Activity被系统自动销毁,而下一次系统又要把这个Activity切换到前台,系统就会自动重新创建这个Activity,此时才会触发onRestoreInstanceState()
被调用,在这个时候,我们就可以添加恢复数据的逻辑了。
保存数据时,
Bundle
当中;@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
TextView formula = (TextView) findViewById(R.id.formula_area);
String strFormula = formula.getText().toString();
outState.putString("KEY_FORMULA_AREA", strFormula);
TextView result = (TextView) findViewById(R.id.result_area);
String strResult = result.getText().toString();
outState.putString("KEY_RESULT_AREA", strResult);
}
恢复数据时,
Bundle
中,取出之前保存的数据;@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
TextView formula = (TextView) findViewById(R.id.formula_area);
String strFormula = savedInstanceState.getString("KEY_FORMULA_AREA");
formula.setText(strFormula);
TextView result = (TextView) findViewById(R.id.result_area);
String strResult = savedInstanceState.getString("KEY_RESULT_AREA");
result.setText(strResult);
}
至此,计算器横竖屏旋转时代功能就添加完毕了。