一、Activity生命周期
1.1实验内容
重写MainActivity中的onCreate,onStart,onResume,onPause,onStop,onDestroy,onRestart方法。为每个方法增添一行调试输出,观察Activity的生命周期。
1.2实验步骤
(1)新建Android项目ActivityLifeCycle,重写MainActivity中的onCreate 、onStart、 onResume、 onPause、 onStop、 onDestroy和 onRestart方法。为每个方法增添一行调试输出,表示该方法得到运行。为用户提供一个退出按钮,使得用户能够退出程序。其中MainActivity.java的代码如下:
package com.wp.activitylifecycle;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static String TAG="LIFECYCLE";
private Button finishButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG,"1.onCreate");
finishButton=(Button)findViewById(R.id.finishButton);
finishButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
public void onStart() {
super.onStart();
Log.v(TAG,"2.onStart");
}
@Override
public void onResume() {
super.onResume();
Log.v(TAG,"3.onResume");
}
@Override
public void onPause() {
super.onPause();
Log.v(TAG,"4.onPause");
}
@Override
public void onStop() {
super.onStop();
Log.v(TAG,"5.onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v(TAG,"6.onDestroy");
}
@Override
public void onRestart() {
super.onRestart();
Log.v(TAG,"7.onRestart");
}
}
(2)activity_main.xml文件的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="状态演示"/>
<Button
android:id="@+id/finishButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/show"
android:text="退出"/>
</RelativeLayout>
1.3实验结果
二、各种控件
2.1实验内容
爱好选择使用CheckBox控件,性别使用RadioButton控件以及RadioGroup控件。地址选择使用Spinner控件。点击控件时弹框提示。
2.2实验步骤
(1)1.编写布局文件activity_main.xml.在文件中用相对布局添加CheckBox, RadioGroup,RadioButton和Spinner控件,定义id和相对位置。布局文件activity_main.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/hobby"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="爱好选择" />
<CheckBox
android:id="@+id/read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/hobby"
android:text="阅读" />
<CheckBox
android:id="@+id/sports"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/read"
android:text="运动" />
<TextView
android:id="@+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/sports"
android:text="性别选择" />
<RadioGroup
android:id="@+id/gender1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/gender"
android:orientation="horizontal">
<RadioButton
android:id="@+id/male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男"
android:checked="true"/>
<RadioButton
android:id="@+id/female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="女" />
</RadioGroup>
<TextView
android:id="@+id/address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/gender1"
android:text="地址选择"/>
<Spinner
android:id="@+id/address1"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_below="@id/address"/>
</RelativeLayout>
(2)编写MainActivity.java的文件,MainActivity.java的代码如下:
package com.wp.widget;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private CheckBox read;
private CheckBox sports;
private RadioGroup gender1;
private RadioButton male;
private RadioButton female;
private static String[] addresses=new String[]{"湖南","湖北","广东"};
private Spinner addressSpinner;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
read=findViewById(R.id.read);
sports=findViewById(R.id.sports);
gender1=findViewById(R.id.gender1);
male=findViewById(R.id.male);
female=findViewById(R.id.female);
addressSpinner=findViewById(R.id.address1);//生成适配器
ArrayAdapter<String>addressAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,addresses);//设置显示样式和数据
addressAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
addressSpinner.setAdapter(addressAdapter);
View.OnClickListener checkboxListener=new View.OnClickListener() {
@Override
public void onClick(View v) {
String text="您选择的爱好是:";
if(read.isChecked())
text+=text+read.getText();
if(sports.isChecked())
text+=sports.getText();
Toast.makeText(MainActivity.this,text,Toast.LENGTH_LONG).show();
}
};
read.setOnClickListener(checkboxListener);
sports.setOnClickListener(checkboxListener);
gender1.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton radioButton=findViewById(checkedId);
Toast.makeText(MainActivity.this,"您选择的性别是:"+radioButton.getText(),Toast.LENGTH_LONG).show();
}
});
addressSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?>arg0,View arg1,int position,long id)
{
Toast.makeText(MainActivity.this,"您选择的地址是:"+addresses[position],Toast.LENGTH_LONG).show();
}
@Override
public void onNothingSelected(AdapterView<?>arg0){}
});
}
}
2.3实验结果
三、各种布局
3.1实验内容
提示语句使用TextView,输入使用EditText,取消/下一步使用Button。要求五个布局文件排列出同样的效果总体的提示占据一行;往下,用户名和密码占据屏幕的20%,输入占据另外80%;再往下,按钮靠右摆放。请用尽量多的布局方式排列出同样或类似的效果。请注意在不同的分辨率下,效果相同或类似。效果图如图所示:
3.2实验步骤
(1)线性布局(LinearLayout)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:gravity="right"
android:text="用户名:" />
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:ems="12" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:gravity="right"
android:text="密码:" />
<EditText
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_height="wrap_content"
android:ems="12"
android:inputType="textVisiblePassword" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一步" />
</LinearLayout>
</LinearLayout>
(2)网格布局(GridLayout)
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="3"
android:rowCount="4">
<TextView
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_row="0"
android:layout_columnSpan="3"
android:gravity="center"
android:text="实验实例" />
<TextView
android:id="@+id/user_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="用户名:" />
<EditText
android:id="@+id/user"
android:layout_width="wrap_content"
android:layout_row="1"
android:layout_columnSpan="2"
android:layout_gravity="fill" />
<TextView
android:id="@+id/pass_hint"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:" />
<EditText
android:id="@+id/pass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_row="2"
android:layout_columnSpan="2"
android:layout_gravity="fill"
android:inputType="textPassword" />
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_row="3"
android:layout_column="1"
android:layout_columnWeight="1"
android:layout_gravity="fill"
android:text="取消" />
<Button
android:id="@+id/next"
android:layout_columnWeight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|fill"
android:layout_row="3"
android:layout_column="2"
android:text="下一步" />
</GridLayout>
(3)相对布局(RelativeLayout)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/example"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="20sp"
android:text="实验示例" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_below="@id/example"
android:layout_alignBaseline="@id/edit1"
android:text="用户名: "/>
<EditText
android:id="@+id/edit1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/example"
android:layout_toRightOf="@id/name"/>
<TextView
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_alignBaseline="@id/edit2"
android:textSize="20sp"
android:text="密码:"/>
<EditText
android:id="@+id/edit2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/edit1"
android:layout_toRightOf="@id/password"/>
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@id/password"
android:text="取消"/>
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/password"
android:layout_toLeftOf="@id/cancel"
android:text="下一步"/>
</RelativeLayout>
3.3实验结果
四、选项菜单、Actionbar/Toolbar与Fragment
4.1实验内容
实验内容包括三个:
内容一,使用选项菜单,为应用程序添加退出选项。将退出选项放置在ActionBar中,具体效果如下所示,用户点击退出选项,则退出该应用。
内容二,利用Toolbar技术替换ActionBar技术。结合选项菜单,实现内容一。
内容三,利用Toolbar、控件、选项菜单和碎片Fragment技术实现下述类似功能。当用户点击“登陆”按钮,显示登陆界面,点击“注册”按钮,显示注册界面。不同选项,产生不同的显示效果。
4.2实验步骤
(1)使用选项菜单,为应用程序添加退出选项。
新建res/menu资源文件夹,在main.xml文件中定义ActionBar的样式,main.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/main_menu"
android:text="退出"
app:showAsAction="always|withText"
android:icon="@drawable/exit"/>
</menu>
在要使用该菜单的Activity中,重写onCreateOptionsMenu(Menu menu)方法,完成菜单初始化。在要使用该菜单的Activity中,重写onOptionsItemSelected(MenuItem item)方法,完成菜单选项点击事件,为菜单选项添加功能,MainActivity.java的代码如下:
package com.wp.barfragment;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show=findViewById(R.id.show);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId())
{
case R.id.main_menu:
show.setText("退出被点击"+item.getItemId());
finish();
break;
}
return super.onOptionsItemSelected(item);
}
}
(2)使用ToolBar技术替代ActionBar技术。
在项目中两个themes.xml删除Actionbar,并将DarkActionBar替换为NoActionBar。
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Four" parent="Theme.MaterialComponents.DayNight.NoActionBar">
在activity_main.xml布局文件中使用Toolbar控件。
<androidx.appcompat.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar"
app:popupTheme="@style/Theme.AppCompat.Light"/>
在MainActivity.java中使用Toolbar控件。用其充当ActionBar的功能。添加属性。
toolbar = findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
(3)3.利用Toolbar、控件、选项菜单和碎片Fragment技术实现下述类似功能。当用户点击“登陆”按钮,显示登陆界面,点击“注册”按钮,显示注册界面。不同选项,产生不同的显示效果。
新建两个fragment文件fragment_a.xml,fragment_b.xml文件,fragment_a.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:weightSum="1.0"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:gravity="right"
android:text="用户名:" />
<EditText
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:ems="12" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:gravity="right"
android:text="密码:" />
<EditText
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_height="wrap_content"
android:ems="12"
android:inputType="textVisiblePassword" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下一步" />
</LinearLayout>
</LinearLayout>
fragment_b.xml的代码如下:
<RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/hobby_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="爱好选择" />
<CheckBox
android:id="@+id/read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/hobby_hint"
android:text="阅读"/>
<CheckBox
android:id="@+id/sports"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/hobby_hint"
android:layout_marginLeft="100dp"
android:text="运动" />
<TextView
android:id="@+id/gender_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/sports"
android:text="性别选择" />
<RadioGroup
android:id="@+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/gender_hint"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男"
android:checked="true" />
<RadioButton
android:id="@+id/female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="女" />
</RadioGroup>
</RelativeLayout>
activity_main.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<TextView
android:id="@+id/b_fragment_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10dp"
android:text="登录"/>
<TextView
android:id="@+id/a_fragment_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="10dp"
android:text="注册"/>
</androidx.appcompat.widget.Toolbar>
<FrameLayout
android:id="@+id/root"
android:layout_below="@id/tool_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</RelativeLayout>
(2)编写main.xml文件,其代码如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/main_menu"
android:text="退出"
app:showAsAction="always|withText"
android:icon="@drawable/exit"/>
</menu>
AFragment和BFragment类继承Fragment,重写onCreateView方法,AFragment的代码如下:
package com.wp.fragment;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class AFragment extends Fragment {
public View onCreateView(LayoutInflater inflater,@Nullable ViewGroup container,Bundle savedInstanceState)
{
View view=inflater.inflate(R.layout.fragment_a,null);
return view;
}
}
BFragment的代码如下:
package com.wp.fragment;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class BFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState)
{
View view=inflater.inflate(R.layout.fragment_b,null);
return view;
}
}
(3)编写MainActivity.java文件,其代码如下:
package com.wp.fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity {
private TextView show;
private Toolbar toolbar;
private TextView aFragmentShowT;
private TextView bFragmentShowT;
private AFragment aFragment;
private BFragment bFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
show = findViewById(R.id.show);
aFragment=new AFragment();
bFragment=new BFragment();
aFragmentShowT=findViewById(R.id.a_fragment_show);
bFragmentShowT=findViewById(R.id.b_fragment_show);
aFragmentShowT.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
replaceFragment(aFragment);
}
});
bFragmentShowT.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
replaceFragment(bFragment);
}
});
}
private void replaceFragment(Fragment fragment)
{
FragmentManager fm=getSupportFragmentManager();
FragmentTransaction ftr=fm.beginTransaction();
ftr.replace(R.id.root,fragment);
ftr.commit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId())
{
case R.id.main_menu:
show.setText("退出被点击"+item.getItemId());
finish();
break;
}
return super.onOptionsItemSelected(item);
}
}
4.3实验结果
五、Intent和Activity
5.1实验内容
实验内容包括两个部分。内容一要求能够使用Intent开启第二个Activity,并传递对应信息到第二个Activity。具体要求如下所示。主界面(MainActivity)如下图所示:
点击“下一步”按钮,开启ResultActivity活动组件,ResultActivity获得用户的登陆信息,并在界面中显示,如下图所示:
实验内容二。要求能够通过Intent开启第二个Activity,并从第二个Activity获得返回的信息。具体要求如下所示。主界面(MainActivity)如下图所示,多提供一个地址选择:
点击“地址选择”按钮,则出现下图所示的AdressSelectedActivity:
选择地址后,回到主界面MainActivity,主界面显示用户的地址选择。如下图所示:
点击“下一步”,则进入界面ResultActivity,显示用户的各种信息,如下图所示:
5.2实验步骤
(1)整个实验主页面的布局文件activity_main.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context=".MainActivity">
<TextView
android:id="@+id/show"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="实验示例" />
<LinearLayout
android:id="@+id/name"
android:layout_below="@id/show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:gravity="right"
android:text="用户名:" />
<EditText
android:id="@+id/user_name"
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_below="@id/name"
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:gravity="right"
android:text="密码:" />
<EditText
android:id="@+id/user_passw"
android:layout_width="0dp"
android:layout_weight="0.8"
android:layout_height="wrap_content"
android:inputType="textPassword" />
</LinearLayout>
<Button
android:id="@+id/next"
android:layout_below="@id/password"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="下一步" />
<Button
android:id="@+id/cancel"
android:layout_toLeftOf="@id/next"
android:layout_alignTop="@id/next"
android:layout_marginRight="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消" />
<Button
android:id="@+id/address_select"
android:layout_below="@id/password"
android:layout_alignParentLeft="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="地址选择"/>
<TextView
android:id="@+id/address_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/password"
android:layout_toRightOf="@id/address_select"/>
</RelativeLayout>
(2)本实验中MainActivity启动ResultActivity采用的是StartActivity形式。其中要通过Intent来传递数据。MainActivity发送数据分为四个步骤:建立Intent;新建Bundle,并设置数据;使用Intent携带Bundle和启动Activity。
ResultActivity获取数据对应三个步骤:获得MainActivity传递来的Intent;获得Intent携带的Bundle和通过Bundle获得对应数据。其中MainActivity.java代码如下:
package com.wp.intent;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button nextB;//下一步按键
private EditText userNameE;//用户名控件
private EditText userPassE;//密码控件
private Button button;//地址按键
private TextView addressShow;//地址显示控件
private String addr;//地址信息
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获得各种控件
nextB=findViewById(R.id.next);
userNameE=findViewById(R.id.user_name);
userPassE=findViewById(R.id.user_passw);
//设置点击事件
nextB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person p=new Person();
p.setUserName(userNameE.getText().toString());
p.setUserPassw(userPassE.getText().toString());
//新建意图
Intent intent=new Intent(MainActivity.this,ResultActivity.class);
Bundle data=new Bundle(); //创建Bundle,放置Person对象
data.putSerializable("person",p);
intent.putExtras(data); //intent携带Bundle
intent.putExtra("address",addr);//再次利用intent将地址信息传送过去
startActivity(intent);//启动对应的Activity
}
});
button=findViewById(R.id.address_select);
addressShow=findViewById(R.id.address_show);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this,AdressSelectedActivity.class);
startActivityForResult(intent,0);
//如果有值返回,
//则使用startActivityForResult方法启动其它Activity
//第二个参数为请求码,一个Activity可能开启多个请求
}
});
}
protected void onActivityResult(int requestCode,int resultCode,Intent intent)//注意此处是向MainActivity传送地址信息用于显示,并没有向ResultActivity传送信息
{
super.onActivityResult(requestCode,resultCode,intent);
//如果请求码是0且返回的结果码为Activity.RESULT_OK
//请求的Activity也可以返回多种结果,如RESULT_CANCELED
if(requestCode==0&&resultCode== Activity.RESULT_OK)
{
Bundle data=intent.getExtras(); //取出数据
String address=data.getString("province");
addr=address;//注意此处一定要将从AdressSelectedActivity传来的地址信息用另外一个字符串变量表示,便于和上面的Pesron对象一起传送给ResultActivity
addressShow.setText(address);//显示数据
}
}
}
(3)ResultActivity.java的代码如下:
package com.wp.intent;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import java.sql.BatchUpdateException;
public class ResultActivity extends AppCompatActivity {
private TextView personShow;//显示用控件
private TextView addressShow;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
//获取姓名和密码
personShow=findViewById(R.id.person_show);
Intent intent=getIntent();//获得MainActivity传递过来的Intent
Bundle data=intent.getExtras(); //通过Intent获得携带的数据Bundle
Person p=(Person)data.getSerializable("person");//从Bundle中获得对应数据
//获取地址
String addr=intent.getStringExtra("address");
String result="";
if(p!=null)
{
result+="名字是:"+p.getUserName()+"\n";
result+="密码是:"+p.getUserPassw()+"\n";
if(addr==null)//地址为空时则不显示,地址不为空时则显示
{
result+="";
}
else
{
result+="地址是:"+addr+"\n";
}
}
personShow.setText(result); //显示MainActivity传递过来的数据
}
}
(4)MainActivity调用AddressSelectedActivity,需要获得该Activity返回的信息,因此使用了sub-Actvity的启动方式,其启动方式一般可以分为以下三个步骤:以Sub-Activity的方式启动子Activity;设置子Activity的返回值和在父Activity中获取返回值。其中AddressSelectedActivity.java代码如下:
package com.wp.intent;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class AdressSelectedActivity extends ListActivity {
private static String[] address=new String[]{"湖南","湖北","广东"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayAdapter<String>adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,address);
setListAdapter(adapter);
}
@Override
protected void onListItemClick(ListView l, View v, int p, long id) {
super.onListItemClick(l, v, p, id);
//获得intent,并通过intent携带数据返回
Intent intent = getIntent();
Bundle data = new Bundle();
data.putString("province", address[p]);
intent.putExtras(data);
//设置返回码为Activity.RESULT_OK,返回intent
this.setResult(Activity.RESULT_OK, intent);
//本Activity结束,退出该Activity
this.finish();
}
}
(5)activity_result.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ResultActivity">
<TextView
android:id="@+id/person_show"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
(6)我们所有用户信息封装成一个Person类,其代码如下:
package com.wp.intent;
import java.io.Serializable;
public class Person implements Serializable {
private String userName;
private String userPassw;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPassw() {
return userPassw;
}
public void setUserPassw(String userPassw) {
this.userPassw = userPassw;
}
}
5.3实验结果
六、 Service和Thread
6.1实验内容
编写一个计时APP,如下图所示:
用户在点击开始计时的时候,屏幕每秒种刷新一次,记录运行的秒数。点击停止计时,则屏幕停止刷新。用户再次点击“开始计时”时,屏幕继续刷新,重新记录运行的描述,APP要求能在后台长时间的记录运行秒数。同时实现计时的暂停功能,用户能暂停计算并回复计时。
6.2实验步骤
(1)本实验的字体主页面布局activity.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/show_time"
android:layout_width="300dp"
android:layout_height="40dp"
android:textSize="25dp"
android:layout_centerInParent="true"
android:layout_alignParentTop="true"
android:layout_marginTop="20dp"
android:gravity="center"/>
<Button
android:id="@+id/start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始计时"
android:layout_below="@id/show_time"
android:layout_marginLeft="55dp"
android:layout_marginTop="20dp"/>
<Button
android:id="@+id/end_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止计时"
android:layout_below="@id/show_time"
android:layout_toRightOf="@id/start_time"
android:layout_marginLeft="115dp"
android:layout_marginTop="20dp"/>
<Button
android:id="@+id/pause_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停计时"
android:layout_below="@id/show_time"
android:layout_toRightOf="@id/start_time"
android:layout_marginLeft="11.5dp"
android:layout_marginTop="20dp"/>
</RelativeLayout>
(2)MyService.java的代码如下:
package com.wp.servicethread;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
public class MyService extends Service {
private Thread countTimeThread;
int i=1;
private Message msg;//消息
private MyBind myBind;//用于与绑定者通信的myBind
private boolean pause=false;
private final Object lock=new Object();
public class MyBind extends Binder //MyBind对象提供该方法获得MyService对象本身
{
public MyService getService() {
return MyService.this;
}
}
public MyService() {//初始化myBind
myBind = new MyBind();
}
@Override
public IBinder onBind(Intent intent) {//实现Service必须要实现的方法,并返回IBinder类型对象给服务绑定者
return myBind;
}
@Override
public void onCreate()//Service被创建时将回调此方法
{
super.onCreate();
Runnable backgroundTask = new Runnable() {//工作线程的主体
@Override
public void run() {
try {//如果睡眠使被interrupted将跳出循环
while (!Thread.interrupted()) {
if (pause)
onPause();
msg = new Message();
msg.what = 0x001;//设置消息类型
Bundle data = new Bundle();//生成Buddle对象携带数据
data.putInt("value", i);
msg.setData(data);
MainActivity.myHandler.sendMessage(msg);//利用MainActivity的myHandler发送消息
i++;
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
countTimeThread = new Thread(backgroundTask);//生成新的线程
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!countTimeThread.isAlive())//isAlive方法用于判断countTimeThread线程是否被开启
countTimeThread.start();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
countTimeThread.interrupt();
}
public void pauseThread() {
this.pause = true;
}
public void onPause() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void resumeThread() {
this.pause = false;
synchronized (lock) {
lock.notify();
}
}
}
(3)MainActivity.java的代码如下:
package com.wp.servicethread;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.sql.Connection;
public class MainActivity extends AppCompatActivity{
private Button startButton;//开始计时按钮
private Button endButton;//停止计时按钮
private Button pauseButton;//暂停计时按钮
private TextView showValue;//显示计时
private Intent intent;//启动service所用意图
public static Handler myHandler;//定义static类型的Handler
private ServiceConnection con=new MyConnection();
private MyService myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获得控件id
startButton = findViewById(R.id.start_time);
endButton = findViewById(R.id.end_time);
pauseButton = findViewById(R.id.pause_time);
showValue = findViewById(R.id.show_time);
myHandler = new Handler(Looper.getMainLooper()) {//构建handler并重写handleMessage方法
@Override
public void handleMessage(Message msg) {//该方法在得到消息时会被系统调用
super.handleMessage(msg);
if (msg.what == 0x001) {//若消息类型是0x001
Bundle data = msg.getData();//获取消息中的数据并显示
int i = data.getInt("value");
showValue.setText("当前已经运行" + i + "秒");
}
}
};
intent = new Intent(this, MyService.class);//显式方式调用MyService
startButton.setOnClickListener(new View.OnClickListener() {//设置启动按钮点击事件
@Override
public void onClick(View v) {
if (myService == null) {
startService(intent);//开启服务
bindService(intent, con, Context.BIND_AUTO_CREATE);
} else
myService.resumeThread();
}
});
endButton.setOnClickListener(new View.OnClickListener() {//设置停止按钮点击事件
@Override
public void onClick(View v) {
if (myService != null) {
unbindService(con);
myService = null;
} else
showValue.setText("请点击开始计时!");
stopService(intent);//关闭服务
}
});
pauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (myService != null) {
myService.pauseThread();
} else
showValue.setText("失败!");
}
});
}
class MyConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder binder){
myService=((MyService.MyBind)binder).getService();
if(myService!=null){
}
else
showValue.setText("获取时间失败");
}
@Override
public void onServiceDisconnected(ComponentName name){
myService=null;
}
}
}
6.3实验结果