Android四大组件之-Activity的创建与应用
一、Activity的创建与生命周期
1.Activity的创建
1.创建一个layout xml布局文件
2.创建一个java类继承Activity或者AppCompatActivity
3.重写onCreate()方法,在onCreate()方法中调用setContentView()方法设置要显示的layout文件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
4.在AndroidManifest.xml文件中注册Activity
<activity android:name=".MainActivity2"></activity>
做完以上4步就已经完成了一个Activity的创建,Android Studio工具还提供了更快捷的方法,直接鼠标右键-new - Activity - 选择任意一种布局的activity - 重命名一下Activity Name和Layout Name点击Finish完成创建。
2.Activity的生命周期
1.启动activity时依次调用:onCreate,onStart,onResume
2.按back键时依次调用:onPause,onStop,onDestroy
3.按home键或者跳转到其他页面时依次调用:onPause,onStop
4.从其他页面按back键返回时依次调用:onRestart,onStart,onResume
5.横竖屏切换时依次调用: onPause ,onStop, onDestroy,onCreate, onStart,onResume
从activity1跳转到activity2时依次调用:
activity1的onPause
activity2的onCreate
activity2的onStart
activity2的onResume
activity1的onStop
从activity2按back键返回activity1时依次调用:
activity2的onPause
activity1的onRestart
activity1的onStart
activity1的onResume
activity2的onStop
activity2的onDestroy
可复制以下代码运行,自行查看log打印确认
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("MainActivity", "onCreate()");
}
@Override
protected void onStart() {
super.onStart();
Log.d("MainActivity", "onStart()");
}
@Override
protected void onStop() {
super.onStop();
Log.d("MainActivity", "onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("MainActivity", "onDestroy()");
}
@Override
protected void onPause() {
super.onPause();
Log.d("MainActivity", "onPause()");
}
@Override
protected void onResume() {
super.onResume();
Log.d("MainActivity", "onResume()");
bt = (TextView) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent(MainActivity.this, MainActivity2.class);
startActivity(it);
}
});
}
@Override
protected void onRestart() {
super.onRestart();
Log.d("MainActivity", "onRestart()");
}
}
MainActivity2.java
public class MainActivity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Log.d("MainActivity2", "onCreate()");
}
@Override
protected void onStart() {
super.onStart();
Log.d("MainActivity2", "onStart()");
}
@Override
protected void onStop() {
super.onStop();
Log.d("MainActivity2", "onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("MainActivity2", "onDestroy()");
}
@Override
protected void onPause() {
super.onPause();
Log.d("MainActivity2", "onPause()");
}
@Override
protected void onResume() {
super.onResume();
Log.d("MainActivity2", "onResume()");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d("MainActivity2", "onRestart()");
}
}
二、layout布局常用控件用法与详解
Android中有六大布局,分别是: LinearLayout(线性布局),RelativeLayout(相对布局),TableLayout(表格布局) FrameLayout(帧布局),AbsoluteLayout(绝对布局),GridLayout(网格布局) 。
实际运用中,LinearLayout和RelativeLayout用的最多。
1.线性布局
<LinearLayout
android:layout_width="match_parent" //设置该组件的宽度和高度:match_parent表示填满父组件,wrap_content表示组件实际大小
android:layout_height="match_parent"
android:orientation="vertical" //orientation表示布局方向:vertical表示该组件中的子组件会一行一行排列,horizontal表示子组件一列一列的排列
android:divider="@color/black" //divider表示该组件中子组件之间的分割线:可以设置图片或颜色
android:showDividers="middle" //showDividers设置分割线的位置:分别为不显示none,开始处显示beginning,结尾处显示end,两个组件之间显示middle
android:layout_weight="1" //layout_weight设置该控件在父控件中所占的比例大小,用数字表示,可用于子控件
android:background="" //background设置该控件的背景颜色,可用于子控件
android:dividerPadding="10dp"> //设置分割线与组件两边的边距
2.相对布局
<RelativeLayout
android:gravity="center" //gravity用于设置该组件中子组件的对其方式
android:ignoreGravity="@color/black"> //设置该组件中不受gravity影响的组件
除了上述两个属性外,RelativeLayout还有非常详细的子组件定位属性,大致分为以下四类:
a.根据父容器定位属性
右对齐
android:layout_alignParentRight="true"
左对齐
android:layout_alignParentLeft="true"
底部对齐
android:layout_alignParentBottom="true"
顶部对齐
android:layout_alignParentTop="true"
水平居中
android:layout_centerHorizontal="true"
垂直居中
android:layout_centerVertical="true"
中间位置
android:layout_centerInParent="true"
b.根据兄弟组件定位属性
参考兄弟组件的左边
android:layout_toLeftOf="@+id/兄弟组件的id"
参考兄弟组件的右边
android:layout_toRightOf="@+id/aaa"
参考兄弟组件的上方
android:layout_above="@+id/aaa"
参考兄弟组件的下方
android:layout_below="@+id/aaa"
参考兄弟组件的起始位置
android:layout_toStartOf="@+id/aaa"
参考兄弟组件的结束位置
android:layout_toEndOf="@+id/aaa"
对齐参考组件的上边界
android:layout_alignTop="@+id/aaa"
对齐参考组件的下边界
android:layout_alignBottom="@+id/aaa"
对齐参考组件的左边界
android:layout_alignLeft="@+id/aaa"
对齐参考组件的右边界
android:layout_alignRight="@+id/aaa"
c.偏移属性(设置两个组件之间的边距)
设置组件四个方向的偏移距离
android:layout_margin="5dp"
设置组件离左边的偏离距离
android:layout_marginLeft="5dp"
设置组件离右边的偏离距离
android:layout_marginRight="5dp"
设置组件离上边的偏离距离
android:layout_marginTop="5dp"
设置组件离下边的偏离距离
android:layout_marginBottom="5dp"
d.填充属性(设置组件内部元素之间的边距)
往内部元素上下左右四个方向有填充一定边距
android:padding="5dp"
往内部元素的左边填充一定边距
android:paddingLeft="5dp"
往内部元素的右边填充一定边距
android:paddingRight="5dp"
往内部元素的上边填充一定边距
android:paddingTop="5dp"
往内部元素的下边填充一定边距
android:paddingBottom="5dp"
下面两个还没用过,先写上
android:paddingHorizontal="5dp"
android:paddingVertical="5dp"
举例说明:
在以下代码中,两个TextView都是RelativeLayout的子组件,两个TextView的关系是兄弟组件。
id为aaa的TextView没有设置其他属性,所以它的位置默认在界面的左上角。
id为bbb的TextView设置了layout_toRightOf属性,所有它在aaa的右边,然后还设置了layout_alignParentBottom属性,所以它靠近父组件的底部,layout_marginTop属性让他从底部网上偏移了5dp的举例,android:paddingLeft属性让它的文本内容左边有5dp的空白
所以效果如下图:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/aaa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
<TextView
android:id="@+id/bbb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试测试测试测试"
android:layout_toRightOf="@+id/aaa"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp"
android:paddingLeft="60dp"
/>
</RelativeLayout>
3.表格布局:主要用于数据表显示
<TableLayout
android:stretchColumns="0,4" > //stretchColumns表示隐藏列,后面的数字表示第一列和第五列将被隐藏
<TableRow> //一个TableRow表示一行,如果一行中有多个组件则全部放在TableRow中
<TextView />
</TableRow>
<TableRow>
<TextView />
</TableRow>
</TableLayout>
4.帧布局:用于前景显示,设置跳转页面也不会被覆盖的内容
<FrameLayout
android:foreground="@drawable/ic_launcher_background" //foreground设置前景显示内容
android:foregroundGravity="right" > //设置前景显示位置
</FrameLayout>
5.网格布局
<GridLayout
android:layout_gravity="center" //设置对其方式
android:orientation="horizontal" //设置排列方式
android:columnCount="4" //设置列数
android:rowCount="6"> //设置行数
<TextView
android:layout_row="0" //设置组件位于网格的第几行,从0开始
android:layout_column="0" //设置组件位于网格的第几列
android:layout_rowSpan="0" //设置组件横跨几行
android:layout_columnSpan="4" /> //设置组件横跨几列
</GridLayout>
6.绝对布局
四大属性(单位:dp):高度,宽度,坐标x,坐标y
控制大小: android:layout_width:组件宽度 android:layout_height:组件高度
控制位置: android:layout_x:设置组件的X坐标 android:layout_y:设置组件的Y坐标
7.普通控件
文本框:
<TextView
android:id="@+id/tex" //Java文件根据控件ID来操作控件
android:layout_width="match_parent" //layout_width和layout_height设置控件高度和宽度,根据父容器设置具体属性值
android:layout_height="match_parent"
android:background="@color/teal_700"/> //background设置控件背景颜色,可以为图片
//文本属性
android:text=" 设置:" //text设置文本内容,可用@string/id代替,从strings.xml文件中根据id值获取文本内容
android:gravity="center_vertical" //gravity设置文本对齐方式
android:textColor="@color/black" //textColor设置文本颜色
android:textStyle="bold" //textStyle设置文本字体风格**normal**(无效果),**bold**(加粗),**italic**(斜体)
android:textSize="20sp" //textSize设置字体大小,单位sp
//阴影属性
android:shadowColor:设置阴影颜色,需要与shadowRadius一起使用
android:shadowRadius:设置阴影的模糊程度,设为0.1就变成字体颜色了,建议使用3.0
android:shadowDx:设置阴影在水平方向的偏移,就是水平方向阴影开始的横坐标位置
android:shadowDy:设置阴影在竖直方向的偏移,就是竖直方向阴影开始的纵坐标位置
修改文本框内容:先实例化,然后赋值
TextView tex = (TextView) findViewById(R.id.tex);
R.string.teaa是调用strings.xml文件中的字符串,teaa为字符串name
tex.setText(R.string.teaa)
tex.setText(“amdlkgma”) //直接赋值
输入框:
<EditText
//默认提示文本
android:hint="默认提示文本" //文本内容
android:textColorHint="#95A1AA" //文本颜色
android:selectAllOnFocus="true" //点击输入框,全选输入框中的文本内容
android:inputType="phone" //限制输入的内容
常用属性值有:
number :数字 phone:拨号键盘 textPassword:密码 date:日期键盘 time:时间键盘
//控制文本行数
android:minLines="3" //输入文本最小行数
android:maxLines="3" //最大行数
android:singleLine="true" //单行
//控制文本间隔
android:textScaleX="1.5" //设置字与字的水平间隔
android:textScaleY="1.5" //设置字与字的垂直间隔
//设置英文字母大写类型
android:capitalize="sentences" //sentences:仅第一个字母大写;words:每一个单词首字母大小,用空格区分单词;characters:每一个英文字母都大写;默认none
//边距控制
android:marginTop = "5dp" //margin属性设置输入框与其他控件的边距
android:paddingTop = "5dp" //padding属性设置文本与输入框的边距
//输入框操作:
在AndroidManifest.xml文件中本页面activity中添加android:windowSoftInputMode="stateHidden|adjustPan",stateHidden表示隐藏软键盘,adjustPan表示控件不会因为输入法的弹出而发生形变
<activity android:name=".MainActivity" android:windowSoftInputMode="stateHidden|adjustPan">
获取输入框内容
首先实例化输入框:
EditText edt = (EditText)findViewById(R.id.editText);
获取:
String edtt = edt.getText().toString();
清空输入框内容
edt.setText("");
edt.requestFocusFromTouch();
按钮Button和ImageButton
drawable:引用的Drawable位图,我们可以把他放到最前面,就表示组件的正常状态~
state_focused:是否获得焦点
state_window_focused:是否获得窗口焦点
state_enabled:控件是否可用
state_checkable:控件可否被勾选,eg:checkbox
state_checked:控件是否被勾选
state_selected:控件是否被选择,针对有滚轮的情况
state_pressed:控件是否被按下
state_active:控件是否处于活动状态,eg:slidingTab
state_single:控件包含多个子控件时,确定是否只显示一个子控件
state_first:控件包含多个子控件时,确定第一个子控件是否处于显示状态
state_middle:控件包含多个子控件时,确定中间一个子控件是否处于显示状态
state_last:控件包含多个子控件时,确定最后一个子控件是否处于显示状态
按钮监听事件
在onCreate()方法中实例化按钮添加以下代码
Button bus = (Button)findViewById(R.id.bus);
bus.setOnClickListener(new bbb());
新建bbb()方法实现监听事件
class bbb implements View.OnClickListener{
@Override
public void onClick(View view) {
监听到点击该按钮时执行的代码
}
}
图像控件ImageView
android:src="@drawable/pen" //src设置图片路径,图片会按原本大小显示
android:background="@drawable/pen" //background设置图片路径,图片被放大或缩小占满控件
单选框
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"> //orientation设置组件为横向排列还是纵向排列
<RadioButton
android:id="@+id/btnMan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男"
android:checked="true"/> //checked设置默认值,true表示默认选择,false表示默认不选
<RadioButton
android:id="@+id/btnWoman"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女"/>
</RadioGroup>
//获取单选值
在onCreate()方法中实例化按钮添加以下代码
RadioGroup radgroup = (RadioGroup) findViewById(R.id.radioGroup);
radgroup.setOnCheckedChangeListener(new eckedChangeListener());
新建eckedChangeListener()方法实现监听事件
class eckedChangeListener implements RadioGroup.OnCheckedChangeListener {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton radbtn = (RadioButton) findViewById(checkedId);
boolean aaa = radbtn.isChecked(); //判断按钮是否选中
Toast.makeText(getApplicationContext(), "按钮组值发生改变,你选了" + radbtn.getText(), Toast.LENGTH_LONG).show();
}
};
复选框:每个CheckBox都要设置一个id
<CheckBox
android:id="@+id/chb1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="苹果">
</CheckBox>
<CheckBox
android:id="@+id/chb2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="雪梨">
</CheckBox>
<CheckBox
android:id="@+id/chb3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="可乐">
</CheckBox>
<Button
android:id="@+id/buttnos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/but" />
获取复选框的值
CheckBox cb_one = (CheckBox) findViewById(R.id.chb1);
CheckBox cb_two = (CheckBox) findViewById(R.id.chb2);
CheckBox cb_three = (CheckBox) findViewById(R.id.chb3);
开关按钮和图标
<ToggleButton //按钮开关
android:id="@+id/tbtn_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textOff="已打开"
android:textOn="已关闭" />
<Switch //左右滑动的开关
android:id="@+id/swh_status"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:showText="true" //设置是否显示文字
android:textOff="1" //设置关闭时显示的文字
android:textOn="2" //设置打开时显示的文字
进度条
<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal" style设置进度条的样式
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100" //设置进度条的最大值
android:progress="75" /> //设置当前进度值
常用方法:
getMax():返回这个进度条的范围的上限
getProgress():返回进度
拖动条
<SeekBar
android:id="@+id/sb_normal"
android:max="100" //设置滑动最大值
android:progress="80" //设置默认值
/>
用法:
在onCreate中实例化拖动条,设置监听事件setOnSeekBarChangeListener
SeekBar skb = (SeekBar)findViewById(R.id.sb_normal);
skb.setOnSeekBarChangeListener(new setonsjb());
重写OnSeekBarChangeListener中的三个方法:
class setonsjb implements SeekBar.OnSeekBarChangeListener{
TextView tex = (TextView) findViewById(R.id.notex);
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { //onProgressChanged进度改变时触发该方法,获取进度值显示出来
tex.setText("进度:" + progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) { //触碰进度条时触发
Toast.makeText(MainActivity.this, "触碰SeekBar", Toast.LENGTH_SHORT).show();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) { //放开进度条时触发
Toast.makeText(MainActivity.this, "放开SeekBar", Toast.LENGTH_SHORT).show();
}
}
时间控件
文本时钟
<TextClock
android:layout_width="match_parent"
android:layout_height="match_parent"/>
模拟时钟
<AnalogClock
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
三、apk全局参数的应用
直接上代码
MainActivity.java
public class MainActivity extends AppCompatActivity {
//全局参数必须设置为public static
public static String name = "name";
TextView bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (TextView) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = new Intent(MainActivity.this, MainActivity2.class);
startActivity(it);
}
});
}
}
MainActivity2.java
public class MainActivity2 extends AppCompatActivity {
String name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
name = MainActivity.name;
Toast.makeText(MainActivity2.this, name, Toast.LENGTH_SHORT).show();
}
}
四、Activity数据持久化
onCreate()方法带一个参数
public class MainActivity extends AppCompatActivity {
// 1.点击home键回到主页或长按后选择运行其他程序
// 2.按下电源键关闭屏幕
// 3.启动新的Activity
// 4.横竖屏切换时使用
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//判断是否有保存的数据,如果有则直接使用
if (savedInstanceState != null) {
Log.d("onCreate()", savedInstanceState.getString("octopus"));
}
}
//横竖屏切换后调用恢复数据,也可以再ocreate中恢复
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d("onRes", savedInstanceState.getString("octopus"));
}
//横竖屏切换时调用保存数据
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("octopus", "www.baidu.com");
Log.d("onSave()", "save date www.baidu.com");
}
}
onCreate()方法带两个参数
public class MainActivity extends AppCompatActivity {
/*
activity持久化:
1.再manifest配置文件的activity中添加代码android:persistableMode="persistAcrossReboots"
2.重写onCreate方法,带两个参数
3.搭配以下两个方法
onCreate(Bundle):当Activity非正常销毁之后,例如手机旋转,内存不足导致的后台自动销毁。
onCreate(Bundle, PersistableBundle):手机由于过热,没电或者第三方定制Rom由于卡顿而异常关机的情况,能找回之前前台的数据,实际上是一种数据持久化的Activity。
*/
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistableBundle) {
super.onCreate(savedInstanceState, persistableBundle);
setContentView(R.layout.activity_main);
Log.d("调用", "onCreate()");
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
@Override
public void onRestoreInstanceState(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
super.onRestoreInstanceState(savedInstanceState, persistentState);
}
}
五、Activity之间的数据传递
传递一个数据
传递:
Intent d = new Intent(MainActivity.this, MainActivity2.class);
d.putExtra("d", "传递一个简单数据"); //第一个参数为传递的数据名称,第二个参数为具体数据
startActivity(d);
接收:
Intent it = getIntent();
String date = it.getStringExtra("d");
传递多个数据传递:
传递:
Intent i = new Intent(MainActivity.this, MainActivity3.class);
Bundle bl = new Bundle();
bl.putString("a", "第一个数据");
bl.putString("b", "第二个数据");
i.putExtras(bl);
startActivity(i);
接收:
Intent it = getIntent();
String date = it.getStringExtra("a");
String date2 = it.getStringExtra("b");
传递数组传递:
传递:
Intent e = new Intent(MainActivity.this, MainActivity4.class);
Bundle ba = new Bundle();
ba.putStringArray("e", new String[]{"数组中第一个数", "数组中第二个数"});
e.putExtras(ba);
startActivity(e);
接收:
Intent it = getIntent();
String[] str = it.getStringArrayExtra("e");
传递集合
传递:
Intent f = new Intent(MainActivity.this, MainActivity5.class);
ArrayList<String> sites = new ArrayList<String>();
sites.add("Google");
sites.add("Runoob");
sites.add("Taobao");
sites.add("Weibo");
f.putStringArrayListExtra("f", sites);
startActivity(f);
接收:
Intent it = getIntent();
ArrayList<String> sites = it.getStringArrayListExtra("f");
多个Activity间的交互(后一个传回给前一个)
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("MainActivity", "onCreate()");
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent a = new Intent(MainActivity.this, MainActivity2.class);
startActivityForResult(a, 123);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 123 && resultCode == 456) {
Bundle bd = data.getExtras();
String a = bd.getString("a");
Toast.makeText(MainActivity.this, a, Toast.LENGTH_SHORT).show();
}
}
}
MainActivity2.java
public class MainActivity2 extends AppCompatActivity {
Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Log.d("MainActivity2", "onCreate()");
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent it = getIntent();
Bundle bd = new Bundle();
bd.putString("a", "AAAAAAA");
it.putExtras(bd);
setResult(456, it);
finish();
}
});
}
}
六、activity启动时根据横竖屏状态加载不同的布局
public class MainActivity extends AppCompatActivity {
/*
操作步骤:
1.创建横竖屏不同的布局文件,文件名称要相同,创建方法见附图:选中layout文件夹右键new-layout Resource File
2.onCreate()方法中添加横竖屏判断加载布局
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
setContentView(R.layout.activity_main);
} else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setContentView(R.layout.activity_main);
}
}
}
六、隐式启动activity
隐式启动常用于不同应用之间的跳转(例如打开支付宝微信的支付页面),也可用于H5与native之间的交互。隐式启动就是action,category和data的匹配
1.在要启动的activity中添加以下代码
<intent-filter>
<action android:name="my_action"/>
<category android:name="my_category"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
2.创建页面跳转Intent,参数为my_action
action匹配规则:
1.action在Intent-filter可以设置多条
2.intent中必须指定action否则匹配失败且intent中action最多只有一条
3.intent中的action和intent-filter中的action必须完全一样时(包括大小写)才算匹配成功
4.intent中的action只要与intent-filter其中的一条匹配成功即可
category匹配规则:
1.category用于指定当前动作(action)执行的环境,即这个activity在哪个环境中才能被激活。不属于这个环境的,不能被激活
2.如果目标activity想要通过隐式调用方式激活,那么不能没有任何category设置,至少包含一个android.intent.category.DEFAULT
3.一个intent只能有一个action,但是可以有多个category。同一个intent中多个category彼此间是“与”的关系,也就是说一个组件要支持全部的category才能处理该请求。
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.LmplicitStart">
<activity android:name=".MainActivity2">
<intent-filter>
<action android:name="my_action" />
<category android:name="my_category"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
MainActivity.java
public class MainActivity extends AppCompatActivity {
Button bt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent a = new Intent();
//action和category二选一即可
a.setAction("my_action");
a.addCategory("my_category");
startActivity(a);
}
});
}
}
七、双击退出APP
第一种方法:定义一个变量,来标识是否退出
public class MainActivity extends AppCompatActivity {
private static boolean isExit = false;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
isExit = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (!isExit) {
isExit = true;
Toast.makeText(getApplicationContext(), "再按一次退出程序",
Toast.LENGTH_SHORT).show();
// 利用handler延迟发送更改状态信息
mHandler.sendEmptyMessageDelayed(0, 2000);
} else {
AppExit();
}
return false;
}
return super.onKeyDown(keyCode, event);
}
/**
* 完全退出应用程序,包括后台任务
* 需添加权限:android.permission.KILL_BACKGROUND_PROCESSES
*/
public void AppExit() {
try {
finish();
ActivityManager activityMgr = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(this.getPackageName());
System.exit(0);
} catch (Exception ignored) {
}
}
}
第二种方法:保存点击时间
public class MainActivity extends AppCompatActivity {
private long exitTime = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if ((System.currentTimeMillis() - exitTime) > 2000) {
Toast.makeText(getApplicationContext(), "再按一次退出程序",
Toast.LENGTH_SHORT).show();
exitTime = System.currentTimeMillis();
} else {
AppExit();
}
return false;
}
return super.onKeyDown(keyCode, event);
}
public void AppExit() {
try {
finish();
ActivityManager activityMgr = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(this.getPackageName());
System.exit(0);
} catch (Exception ignored) {
}
}
}
八、Activity过场动画
首先添加创建过场动画资源
在res目录下创建anim文件夹,然后将动画资源拖进去
为单个Activity设置进入和退出的过场动画
在Activity启动或者退出时加上这一行代码即可:
overridePendingTransition(R.anim.hyperspace_in, R.anim.hyperspace_out);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,MainActivity2.class));
//页面跳转时添加
overridePendingTransition(R.anim.hyperspace_in, R.anim.hyperspace_out);
}
});
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
//退出时添加
overridePendingTransition(R.anim.push_up_in, R.anim.push_up_out);
}
return super.onKeyDown(keyCode, event);
}
为所有Activity设置进入和退出的过场动画
直接在themes.xml文件中添加以下代码。
添加时要查看APP的style中有没有
<item name="android:windowAnimationStyle">@style/default_animation</item>
没有的话要手动添加上
<style name="default_animation" mce_bogus="1" parent="@android:style/Animation.Activity">
<item name="android:activityOpenEnterAnimation">@anim/push_left_in</item>
<item name="android:activityOpenExitAnimation">@anim/push_up_in</item>
<item name="android:activityCloseEnterAnimation">@anim/push_up_out</item>
<item name="android:activityCloseExitAnimation">@anim/push_left_out</item>
</style>
九、设置Activity全屏的四种方法
1.在onCreate方法中添加一行代码去掉
getSupportActionBar().hide();
2.在themes.xml文件中将style的parrent改为
parent="Theme.AppCompat.Light.NoActionBar
3.在themes.xml文件中的style里面添加以下item
<item name="windowNoTitle">true</item>
4.在把 super.onCreate(savedInstanceState);前面添加以下代码
requestWindowFeature(Window.FEATURE_NO_TITLE);
十、设置对话框风格Activity的两种方法
1.直接引用对话框风格的theme
在AndroidManifest.xml中注册的Activity中添加
android:theme=“@style/Theme.AppCompat.Light.Dialog”
<activity
android:name=".MainActivity5"
android:theme="@style/Theme.AppCompat.Light.Dialog" />
<activity android:name=".MainActivity4" />
2.在themes.xml文件中自定义一个style,然后在Activity中引用
<style name="dialog_style" parent="Theme.ActivityOther">
<!--是否悬浮在activity上-->
<item name="android:windowIsFloating">true</item>
<!-- 设置是否透明 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 背景 -->
<item name="android:background">@null</item>
<!--设置没有窗口标题、dialog标题等各种标题-->
<!-- 无标题 -->
<item name="android:windowNoTitle">true</item>
<item name="android:title">@null</item>
<item name="android:dialogTitle">@null</item>
<!-- 去黑边 -->
<item name="android:windowFrame">@null</item>
<!-- 窗口背景 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 是否变暗 -->
<item name="android:backgroundDimEnabled">false</item>
<!-- 点击空白部分activity不消失 -->
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
十、onWindowFocusChanged方法的应用
回调时机:当Activity得到或者失去焦点的时候回调,
作用:
1.监控Activity是否加载完毕
2.测量控件,获取控件的宽高
3.设置控件进入时的默认值
参数解析:
hasFocus:进入或恢复Actiity时为true,Actvity销毁或者退到后台则为false
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
Log.d("MainActivity4", "Activity加载完毕!");
int[] a = new int[2];
bt.getLocationOnScreen(a);
int x = a[0];
int y = a[1];
int m = bt.getHeight(); //横屏为宽度,竖屏为高度
int n = bt.getWidth();
Log.d("参数为", x + "," + y + "," + m + "," + n);
Log.d("左上角坐标为", x + "," + y);
Log.d("右上角坐标为", (x + n) + "," + y);
Log.d("左下角坐标为", x + "," + (y + m));
Log.d("右上角坐标为", (x + n) + "," + (y + m));
}
}
十一、Activity管理类的使用以及关闭所有acitivity和完全退出app的方法
首先创建一个Activity管理类:
activity管理类解析:
1.创建一个全局变量list
2.创建三个方法:
a.将activity添加到list中
b.在list中删除单个activity
c.关闭list中的所有activity
activity管理类使用:
1.activity启动时在onCreate方法中将activity添加到list中
2.activity关闭时在onDestroy方法中将activity从list中删除
3.退出应用时调用finishAll方法将list中的所有activity关闭
ActivityCollector.java
public class ActivityCollector {
public static LinkedList<Activity> activities = new LinkedList<Activity>();
//添加activity
public static void addActivity(Activity activity) {
activities.add(activity);
}
//删除activity
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
//关闭所有activity
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
在Activity加载完成后调用管理类中添加activity的方法
ActivityCollector.addActivity(this);
在Activity退出时调用管理类中删除activity的方法
ActivityCollector.removeActivity(this);
在整个APP退出时调用管理类中关闭所有activity的方法
/**
* 完全退出应用程序,包括后台任务
* 需添加权限:android.permission.KILL_BACKGROUND_PROCESSES
*/
public void AppExit(Context context) {
try {
ActivityCollector.finishAll();
ActivityManager activityMgr = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.killBackgroundProcesses(context.getPackageName());
System.exit(0);
} catch (Exception ignored) {
}
}
十二、设计堆栈的Activity管理类
开源中国客户端Activity管理类
public class AppManager {
private static Stack<Activity> activityStack;
private static AppManager instance;
private AppManager(){}
/**
* 单一实例
*/
public static AppManager getAppManager(){
if(instance==null){
instance=new AppManager();
}
return instance;
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity){
if(activityStack==null){
activityStack=new Stack<Activity>();
}
activityStack.add(activity);
}
/**
* 获取当前Activity(堆栈中最后一个压入的)
*/
public Activity currentActivity(){
Activity activity=activityStack.lastElement();
return activity;
}
/**
* 结束当前Activity(堆栈中最后一个压入的)
*/
public void finishActivity(){
Activity activity=activityStack.lastElement();
finishActivity(activity);
}
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity){
if(activity!=null){
activityStack.remove(activity);
activity.finish();
activity=null;
}
}
/**
* 结束指定类名的Activity
*/
public void finishActivity(Class<?> cls){
for (Activity activity : activityStack) {
if(activity.getClass().equals(cls) ){
finishActivity(activity);
}
}
}
/**
* 结束所有Activity
*/
public void finishAllActivity(){
for (int i = 0, size = activityStack.size(); i < size; i++){
if (null != activityStack.get(i)){
activityStack.get(i).finish();
}
}
activityStack.clear();
}
/**
* 退出应用程序
*/
public void AppExit(Context context) {
try {
finishAllActivity();
ActivityManager activityMgr= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.restartPackage(context.getPackageName());
System.exit(0);
} catch (Exception e) { }
}
}
总结
关于控件部分,因为常用控件太多,还有一部分常用控件未作说明,以后单独写一篇