0


CH4-程序活动单元Activity

文章目录

目标

  • 熟悉Activity生命周期的方法,能够解释每个方法的作用
  • 掌握Activity的创建、配置、开启和关闭的方式,能够完成创建、配置、开启和关闭Activity
  • 熟悉IntentIntentFilter的内容,能够归纳Intent与IntentFilter的用法
  • 熟悉Activity的任务栈和四种启动模式的内容,能够归纳任务栈和四种启动模式的作用
  • 掌握Activity之间的跳转方式,能够独立实现Activity之间的跳转功能
  • 掌握Fragment的使用,能够完成在Activity中添加Fragment

​ Android中的四大组件分别是Activity、Service、ContentProvider和BroadcastReceiver,其中,Activity是一个负责与用户交互的组件,每个Android应用中都会用Activity来显示界面以及处理界面上一些控件的事件。本章将针对Activity组件进行详细讲解,其他组件的介绍会在后续章节中讲解。

一、Activity的生命周期

目标

  • 熟悉Activity生命周期的状态,能够归纳Activity生命周期的5种状态
  • 熟悉Activity生命周期的方法,能够归纳Activity生命周期的7个方法

1.1 生命周期状态

​ 每个人都是有生命的,在每个人出生到老去的过程中需要经历幼儿期、少年期、青春期、成年期和老年期5个阶段。

image-20220227223233740

​ Activity与人一样也是有“生命”的,Activity从创建到销毁的整个过程就是Activity的生命周期,Activity的生命周期包含5种状态,这5种状态好比人类生命过程中经历的5个阶段。

image-20220227223310588

1.2 生命周期方法

Activity的

生命周期

包括创建、可见、获取焦点、失去焦点、不可见、重新可见、销毁等环节,针对每个环节Activity都定义了相关的

回调方法

,Activity中的回调方法具体如下。

(1)onCreate():创建态,Activity

创建时

调用,通常做一些初始化设置。

(2)onStart():启动态,Activity即将

可见时

调用。

(3)onResume():运行态,Activity

获取焦点时

调用。

(4)onPause():暂停态,当前Activity被其他Activity

覆盖或屏幕锁屏时

调用。

(5)onStop():停止态,Activity对用户

不可见时

调用。

(6)onRestart():重启态,Activity从停止状态到

再次启动时

调用。

(7)onDestroy():销毁态,Activity

销毁时

调用。

​ 为了帮助开发者更好地理解Activity的生命周期,Google公司提供了Activity的

生命周期模型

,如下图所示。

image-20220227223457161

第一次运行程序

时:

调用的生命周期方法为:onCreate() -> onStart() -> onResume()。

退出程序

时:

调用的生命周期方法为:onPause() -> onStop() -> onDestory()。

横竖屏切换时Activity的生命周期

​ 当手机横竖屏切换时,程序会根据AndroidManifest.xml文件中Activity的configChanges属性值的不同而调用相应的生命周期方法。

(1)

没有设置configChanges属性

的值

​ 当由竖屏切换为横屏时,调用的方法依次是onPause()、onStop()、onDestory()、onCreate()、onStart()和onResume()的方法。

(2)设置configChanges属性的值

<activityandroid:name=".MainActivity"android:configChanges="orientation|keyboardHidden"/>
    打开程序时同样会依次调用onCreate()、 onStart()、onResume()方法,但是当进行横竖屏切换时不会再执行其他的生命周期方法。

​ 如果希望某一个界面一直处于竖屏或者横屏状态,并且此状态不随手机的晃动而改变,此效果可以通过在清单文件中设置Activity的

screenOrientation属性

来实现。

竖屏:android:screenOrientation=“portrait”
横屏:android:screenOrientation=“landscape”

src\main\java\cn\itcast\activitylifecycle\MainActivity.java

package cn.itcast.activitylifecycle;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;publicclassMainActivityextendsAppCompatActivity{@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
        Log.i("MainActivity","调用onCreate()");}@OverrideprotectedvoidonStart(){super.onStart();
        Log.i("MainActivity","调用onStart()");}@OverrideprotectedvoidonResume(){super.onResume();
        Log.i("MainActivity","调用onResume()");}@OverrideprotectedvoidonPause(){super.onPause();
        Log.i("MainActivity","调用onPause()");}@OverrideprotectedvoidonStop(){super.onStop();
        Log.i("MainActivity","调用onStop()");}@OverrideprotectedvoidonDestroy(){super.onDestroy();
        Log.i("MainActivity","调用onDestroy()");}@OverrideprotectedvoidonRestart(){super.onRestart();
        Log.i("MainActivity","调用onRestart()");}}

image-20220228140549127

二、Activity的创建、配置、启动和关闭

目标

  • 掌握Activity的创建、配置、启动和关闭方式,能够完成创建、配置、开启和关闭Activity

2.1 创建Activity

​ 选中程序的包名右击选择【New】->【Activity】->【Empty Activity】选项,填写Activity信息,完成创建。

image-20220228141759747

2.2 配置Activity

​ 在Android程序中,创建Activity可以使用Java类继承Activity的方式实现。使用此种方式创建Activity时,需要在清单文件的标签中配置Acitivity。

<activityandroid:name="cn.itcast.activitybasic.SecondActivity"/>

​ 如果

不配置Activity

,则运行程序时,程序会抛出运行时异常。

image-20220228141910816

在清单文件中引用Activity的方式

​ 如果Activity所在的包与AndroidManifest.xml文件的标签中通过package属性指定的包名一致,则android:name属性的值可以直接设置为“.Activity名称”,以SecondActivity为例,示例代码如下:

<activityandroid:name=".SecondActivity"></activity>

2.3 启动和关闭Activity

  1. 启动Activity:startActivity()方法

以启动SecondActivity为例,示例代码如下

Intent intent =newIntent(MainActivity.this,SecondActivity.class);startActivity(intent);
  1. 关闭Activity:finish()方法

如果想要关闭当前的Activity,可以调用Activity提供的finish()方法。

三、Intent与IntentFilter

目标

  • 掌握两种Intent类型的使用方式,能够灵活使用Intent的两种类型
  • 掌握IntentFilter属性的匹配规则,能够独立配置IntentFilter的3个属性

3.1 Intent

​ Intent被称为意图,它不仅可以指定当前组件要执行的动作,还可以在不同组件之间进行数据传递。根据开启目标组件的方式不同,Intent被分为两种类型,分别为显式Intent和隐式Intent。

image-20220228150252185

显式意图

​ 显式Intent指的是直接指定目标组件,例如,使用Intent显式指定要跳转的目标Activity,示例代码如下:

//this当前Activity        SecondActivity.class要启动的Activity  
Intent intent =newIntent(this, SecondActivity.class);startActivity(intent);//启动Activity

隐式意图

​ 隐式Intent不会明确指出需要激活的目标组件,它被广泛地应用在不同应用程序之间传递消息。

Android系统会使用IntentFilter匹配属性action、data、category,这3个属性的具体介绍如下:

  • action:表示Intent对象要完成的动作。
  • data:表示Intent对象中传递的数据。
  • category:表示为action添加的额外信息。

在清单文件中,配置SecondActivity的action为“cn.itcast.START_ACTIVITY”的代码如下所示:

<activityandroid:name=".SecondActivity"><intent-filter><!--设置action动作,当代码中的action与该action相匹配时启动该组件。--><actionandroid:name="cn.itcast.START_ACTIVITY"/><categoryandroid:name="android.intent.category.DEFAULT"/></intent-filter></activity>

在程序的MainActivity中开启SecondActivity的示例代码如下:

  Intent intent =newIntent();//  设置action动作,当与清单文件中的action相匹配时启动目标组件。
  intent.setAction("cn.itcast.START_ACTIVITY");startActivity(intent);

​ 注意:在使用隐式Intent开启Activity时,系统会默认为该Intent添加category的属性name的值为“android.intent.category.DEFAULT”,所以将SecondActivity对应的标签中,属性android:name的值设置为“android.intent.category.DEFAULT”。

3.2 IntentFilter

​ 当发送一个隐式Intent后,Android系统会将它与程序中的每一个组件的过滤器进行匹配,匹配属性有action、data和category,需要这3个属性都匹配成功才能唤起相应的组件。

(1)action属性匹配规则

action属性用来指定Intent对象的动作,具体示例代码如下:

<intent-filter><actionandroid:name="android.intent.action.EDIT"/><actionandroid:name="android.intent.action.VIEW"/>
       ......
</intent-filter>
  • 只要Intent携带的action与其中一个标签中action的声明相同,action属性就匹配成功。

注意:在清单文件中为Activity添加标签时,必须添加action属性,否则隐式Intent无法开启该Activity。

(2)data属性匹配规则

​ data属性用来指定数据的

URI

或者数据

MIME

类型,它的值通常与Intent的action属性有关联,具体示例代码如下:

<intent-filter><dataandroid:mimeType="video/mpeg"android:scheme="http......"/><dataandroid:mimeType="audio/mpeg"android:scheme="http......"/>
       ......
</intent-filter>
  • 隐式Intent携带的data数据只要与IntentFilter中的任意一个data声明相同,data属性就匹配成功。

(3)category属性匹配规则

category属性用于为action添加额外信息,一个IntentFilter可以不声明category属性,也可以声明多个category属性,具体示例代码如下:

<intent-filter><categoryandroid:name="android.intent.category.DEFAULT"/><categoryandroid:name="android.intent.category.BROWSABLE"/>
     ......
</intent-filter>
  • 一个IntentFilter可以不声明category属性,也可以声明多个category属性。
  • 隐式Intent中声明的category必须全部能够与某一个IntentFilter中的category匹配才算匹配成功。

​ 注意:IntentFilter中罗列的category属性数量必须大于或者等于隐式Intent携带的category属性数量时,category属性才能匹配成功。如果一个隐式Intent没有设置category属性,那么他可以通过任何一个IntentFilter(过滤器)的category匹配。

四、Activity之间的跳转

目标

  • 掌握Activity之间的数据传递方式,能够使用Intent类与Bundle类传递数据
  • 掌握Activity之间的数据回传方式,能够完成Activity之间的数据回传

4.1 数据传递

​ Android提供的Intent可以在界面跳转时传递数据。使用Intent传递数据有两种方式。

  • 使用Intent的putExtra()方法传递数据
  • 使用Bundle类传递数据

使用Intent的putExtra()方法传递数据

​ Activity之间需要传递不同类型的数据,所以Android系统提供了多个重载的putExtra()方法。

image-20220228182031625

image-20220228182055098

使用Bundle类传递数据

image-20220228182226955

4.2 Activity之间的数据回传

image-20220228182252387

​ Activity之间进行数据回传时包含3个方法,分别是

startActivityForResult()

方法、

setResult()

方法和

onActivityResult()

方法。

(1) startActivityForResult()方法

用于开启一个Activity,当开启的Activity销毁时,会从销毁的Activity中返回数据。

// intent 意图对象// requestCode 表示请求码,用于标识请求的来源startActivityForResult(Intent intent,int requestCode)

(2)setResult() 方法

用于携带数据进行回传,该方法的语法格式如下:

// resultCode 表示返回码,用于标识返回的数据来自哪一个ActivitysetResult(int resultCode, Intent intent)

(3)onActivityResult()方法

用于接收回传的数据,该方法的语法格式如下:

// requestCode 请求码 // resultCode  回传码// data  回传数据onActivityResult(int requestCode,int resultCode, Intent data)

程序会根据传递的参数requestCode与resultCode来识别数据的来源。

  Intent intent =newIntent(MainActivity.this,SecondActivity.class);startActivityForResult(intent,1);//     开启SecondActivity
 Intent intent =newIntent();
 intent.putExtra("data","Hello MainActivity");setResult(2,intent);// 在SecondActivity 中添加返回数据  finish();
@Override//  SecondActivity被销毁之后在MainActivity中回调onActivityResult()方法,接收回传的数据protectedvoidonActivityResult(int requestCode,int resultCode, Intent data){super.onActivityResult(requestCode, resultCode, data);if(requestCode ==1&&resultCode ==2){
          String acquiredData= data.getStringExtra("data"); 
          Toast.makeText(MainActivity.this,acquiredData,Toast.LENGTH_SHORT).show();}}

4.3 实战演练—小猴子摘桃

​ 本节我们将通过一个小猴子摘桃的案例来演示Activity之间是如何进行数据回传的,本案例的界面效果如下图所示。

image-20220228183227009

res\layout\activity_main.xml

创建首页界面
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="50dp"android:background="#008577"android:gravity="center"android:text="首页"android:textColor="@android:color/white"android:textSize="20sp"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/bg"android:gravity="center_vertical"><ImageViewandroid:id="@+id/iv_monkey"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/monkey"/><Buttonandroid:id="@+id/btn_peach"android:layout_width="80dp"android:layout_height="30dp"android:layout_marginLeft="30dp"android:layout_marginTop="20dp"android:layout_toRightOf="@id/iv_monkey"android:background="@drawable/btn_peach"android:text="去桃园"android:textColor="@android:color/black"/><ImageViewandroid:id="@+id/iv_peach"android:layout_width="45dp"android:layout_height="35dp"android:layout_centerHorizontal="true"android:layout_marginTop="80dp"android:src="@drawable/peach_pic"/><TextViewandroid:id="@+id/tv_count"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="85dp"android:layout_toRightOf="@id/iv_peach"android:text="摘到0个"android:textColor="@android:color/black"android:textSize="16sp"/></RelativeLayout></LinearLayout>

pickpeach\MainActivity.java

实现首页界面的显示效果
package cn.itcast.pickpeach;import android.content.Intent;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.TextView;publicclassMainActivityextendsAppCompatActivity{private Button btn_peach;private TextView tv_count;privateint totalCount =0;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();}privatevoidinit(){
        btn_peach =findViewById(R.id.btn_peach);
        tv_count =findViewById(R.id.tv_count);
        btn_peach.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View view){
                Intent intent =newIntent(MainActivity.this, PeachActivity.class);startActivityForResult(intent,1);}});}@OverrideprotectedvoidonActivityResult(int requestCode,int resultCode,@Nullable Intent data){super.onActivityResult(requestCode, resultCode, data);if(requestCode ==1&&resultCode==1){int count = data.getIntExtra("count",0);//获取回传的数据
            totalCount = totalCount + count;
            tv_count.setText("摘到"+ totalCount +"个");}}}

res\layout\activity_peach.xml

创建桃园界面
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextViewandroid:layout_width="match_parent"android:layout_height="50dp"android:background="#008577"android:gravity="center"android:text="桃园"android:textColor="@android:color/white"android:textSize="20sp"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/tree_bg"><RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:layout_marginTop="70dp"android:background="@drawable/tree"><Buttonandroid:id="@+id/btn_one"android:layout_width="45dp"android:layout_height="35dp"android:layout_marginLeft="85dp"android:layout_marginTop="25dp"android:background="@drawable/peach_pic"/><Buttonandroid:id="@+id/btn_two"android:layout_width="45dp"android:layout_height="35dp"android:layout_below="@id/btn_one"android:layout_marginLeft="50dp"android:layout_marginTop="5dp"android:background="@drawable/peach_pic"/><Buttonandroid:id="@+id/btn_three"android:layout_width="45dp"android:layout_height="35dp"android:layout_below="@id/btn_one"android:layout_marginLeft="25dp"android:layout_marginTop="5dp"android:layout_toRightOf="@id/btn_two"android:background="@drawable/peach_pic"/><Buttonandroid:id="@+id/btn_four"android:layout_width="45dp"android:layout_height="35dp"android:layout_below="@id/btn_two"android:layout_marginLeft="15dp"android:layout_marginTop="5dp"android:background="@drawable/peach_pic"/><Buttonandroid:id="@+id/btn_five"android:layout_width="45dp"android:layout_height="35dp"android:layout_below="@id/btn_two"android:layout_marginLeft="25dp"android:layout_marginTop="5dp"android:layout_toRightOf="@id/btn_four"android:background="@drawable/peach_pic"/><Buttonandroid:id="@+id/btn_six"android:layout_width="45dp"android:layout_height="35dp"android:layout_below="@id/btn_two"android:layout_marginLeft="25dp"android:layout_marginTop="5dp"android:layout_toRightOf="@id/btn_five"android:background="@drawable/peach_pic"/></RelativeLayout><Buttonandroid:id="@+id/btn_exit"android:layout_width="80dp"android:layout_height="30dp"android:layout_alignParentRight="true"android:layout_alignParentBottom="true"android:layout_margin="50dp"android:background="@drawable/btn_peach"android:text="退出桃园"android:textColor="@android:color/black"/></RelativeLayout></LinearLayout>

pickpeach\PeachActivity.java

实现桃园界面的摘桃效果
package cn.itcast.pickpeach;import android.content.Intent;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.KeyEvent;import android.view.View;import android.widget.Button;import android.widget.Toast;publicclassPeachActivityextendsAppCompatActivityimplementsView.OnClickListener{private Button btn_one, btn_two, btn_three, btn_four, btn_five,btn_six,btn_exit;privateint count=0;//桃子个数@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_peach);init();}privatevoidinit(){
        btn_one =findViewById(R.id.btn_one);
        btn_two =findViewById(R.id.btn_two);
        btn_three =findViewById(R.id.btn_three);
        btn_four =findViewById(R.id.btn_four);
        btn_five =findViewById(R.id.btn_five);
        btn_six =findViewById(R.id.btn_six);
        btn_exit =findViewById(R.id.btn_exit);
        btn_one.setOnClickListener(this);
        btn_two.setOnClickListener(this);
        btn_three.setOnClickListener(this);
        btn_four.setOnClickListener(this);
        btn_five.setOnClickListener(this);
        btn_six.setOnClickListener(this);
        btn_exit.setOnClickListener(this);}@OverridepublicvoidonClick(View view){switch(view.getId()){case R.id.btn_one://第一个桃子的点击事件info(btn_one);break;case R.id.btn_two://第二个桃子的点击事件info(btn_two);break;case R.id.btn_three://第三个桃子的点击事件info(btn_three);break;case R.id.btn_four://第四个桃子的点击事件info(btn_four);break;case R.id.btn_five://第五个桃子的点击事件info(btn_five);break;case R.id.btn_six://第六个桃子的点击事件info(btn_six);break;case R.id.btn_exit://“退出桃园”按钮的点击事件returnData();break;}}/**
     * 按钮的点击事件处理
     */privatevoidinfo(Button btn){
        count++;//桃子个数加1
        btn.setVisibility(View.INVISIBLE);
        Toast.makeText(PeachActivity.this,"摘到"+count+"个桃子",
                Toast.LENGTH_LONG).show();}/**
     * 将数据回传到上个界面
     */privatevoidreturnData(){
        Intent intent =newIntent();
        intent.putExtra("count",count);setResult(1,intent);
        PeachActivity.this.finish();}@OverridepublicbooleanonKeyDown(int keyCode, KeyEvent event){if(keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0){returnData();//调用数据回传方法}returnfalse;}}

五、任务栈和启动模式

目标

  • 熟悉Android中的任务栈,能够归纳Activity在任务栈中的存放情况
  • 熟悉Activity的启动模式,能够解释Activity的4种启动模式

5.1 Android中的任务栈

任务栈:一种用来存放Activity实例的容器。

特点:“先进后出”

操作:压栈和出栈

image-20220228184406828

5.2 Activity的启动模式

Activity启动模式有四种,分别是standard、singleTop、singleTask和singleInstance模式。

(1) standard模式

standard模式是Activity的默认启动方式,每启动一个Activity就会在栈顶创建 一个新的实例。

image-20220228184446668

(2)singleTop模式

​ singleTop模式a会判断要启动的Activity实例是否位于栈顶,如果位于栈顶则直接复用,否则创建新的实例。

image-20220228184656654

(3)singleTask模式

    singleTask模式下每次启动该Activity时,系统首先会<font color='limeGreen'>检查栈中是否存在当前Activity实例</font>,如果存在则直接使用,并<font color='limeGreen'>把当前Activity之上的所有实例全部出栈。</font>

image-20220228184738724

(4)singleInstance模式

​ singleInstance模式会启动一个新的任务栈来管理Activity实例,无论从哪个任务栈中启动该Activity,该实例在整个系统中只有一个。

image-20220228184928730

六、使用Fragment

  • 熟悉Fragment的简介和生命周期,能够解释Fragment的定义和生命周期中的方法
  • 掌握Fragment的创建方式,能够独立完成Fragment的创建
  • 掌握在Activity中添加Fragment的方式,能够独立完成在Activity中添加Fragment

6.1 Fragment简介

​ Fragment(碎片)是一种嵌入在Activity中的UI片段,它可以用来描述Activity中的一部分布局。

image-20220228185145348

6.2 Fragment生命周期

​ Fragment不能独立存在,必须嵌入到Activity中使用,所以Fragment生命周期直接受所在的Activity影响。

  • 当在Activity中创建Fragment时,Fragment处于启动状态;
  • 当Activity被暂停时,其中的所有Fragment也被暂停;
  • 当Activity被销毁时,所有在该Activity中的Fragment也被销毁。
  • 当一个Activity处于运行状态时,可以单独地对每一个Fragment进行操作,如添加或删除,当添加时,Fragment处于启动状态。当删除时,Fragment处于销毁状态。

image-20220228185627869

6.3 创建Fragment

与Activity类似,创建Fragment时必须创建一个类继承Fragment。

publicclassNewsListFragmentextendsFragment{@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,
                                         Bundle savedInstanceState){// 第1个参数表示Fragment对应的布局资源ID// 第2个参数表示存放Fragment视图的父视图// 第3个参数表示是否将生成的视图添加到父视图
               View v = inflater.inflate(R.layout.fragment, container,false);return v;}}

注意

Android系统中提供了2个Fragment类,这两个类分别是android.app.Fragment和android.support.v4.app.Fragment。

(1)如果NewsListFragment类继承的是

android.app.Fragment

类,则程序只能兼容3.0版本以上的Android系统。

(2)如果NewsListFragment类继承的是

android.support.v4.app.Fragment

类,则程序可以兼容1.6版本以上的Android系统。

6.4 在Activity中添加Fragment

​ Fragment创建完成后并不能单独使用,还需要将Fragment添加到Activity中。在Activity中添加Fragment有两种方式。

  • 在布局文件中添加Fragment
  • 在Activity中动态加载Fragment

在布局文件中添加Fragment

<fragmentandroid:name="cn.itcast.NewsListFragment"<!--Fragment的全路径名称-->
        android:id="@+id/newslist"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

在Activity中动态加载Fragment

当Activity运行时,也可以将Fragment动态添加到Activity中,具体步骤如下:

(1) 创建一个Fragment的实例对象。

(2) 获取FragmentManager类的实例。

(3) 开启FragmentTransaction(事务)。

(4) 向Activity的布局容器(一般为FrameLayout)中添加Fragment。

(5) 通过commit()方法提交事务。

    NewsListFragment fragment =newNewsListFragment
    FragmentManager fm =getFragmentManager();
    FragmentTransaction beginTransaction = fm.beginTransaction();// 开启事务
    beginTransaction.replace(R.id.ll,fragment);//  添加一个Fragment
    beginTransaction.commit();//   提交事务

6.5 实战演练—仿美团菜单

​ 本节我们以仿美团外卖菜单的案例为例来演示如何在一个Activity中展示两个Fragment,并实现Activity与Fragment之间的通信功能。本案例的界面效果如下图所示。

image-20220228191557819

image-20220228191643418

res\layout\left_layout.xml

搭建左侧菜单栏界面布局
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#f7f8f9"android:gravity="center_horizontal"android:orientation="vertical"><TextViewandroid:id="@+id/tv_recommend"style="@style/tvLeftStyle"android:text="推荐"android:background="@android:color/white"/><TextViewandroid:id="@+id/tv_must_buy"style="@style/tvLeftStyle"android:text="进店必买"/></LinearLayout>

res\layout\right_layout.xml

搭建右侧菜单列表界面布局
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@android:color/white"android:orientation="vertical"><ListViewandroid:id="@+id/lv_list"android:layout_width="match_parent"android:layout_height="wrap_content"android:divider="@null"/></LinearLayout>

res\layout\list_item.xml

搭建菜单列表界面的条目布局
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"android:padding="4dp"><ImageViewandroid:id="@+id/iv_img"android:layout_width="70dp"android:layout_height="70dp"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="8dp"android:layout_marginRight="8dp"android:orientation="vertical"><TextViewandroid:id="@+id/tv_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="2dp"android:textColor="@android:color/black"android:textSize="14sp"/><TextViewandroid:id="@+id/tv_sale"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#868788"android:textSize="12sp"/><TextViewandroid:id="@+id/tv_price"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="2dp"android:textColor="#e85b4d"android:textSize="12sp"/></LinearLayout></LinearLayout>

res\layout\activity_main.xml

搭建菜单界面布局
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns: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:background="@android:color/white"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:layout_marginBottom="4dp"android:background="@color/gray"android:gravity="center_vertical"><TextViewandroid:id="@+id/tv_order"style="@style/tvNavigationBarStyle"android:text="点菜"android:textColor="@android:color/black"/><TextViewandroid:id="@+id/tv_discuss"style="@style/tvNavigationBarStyle"android:layout_toRightOf="@id/tv_order"android:text="评价"android:textColor="@color/dark_gray"/><TextViewandroid:id="@+id/tv_business"style="@style/tvNavigationBarStyle"android:layout_toRightOf="@id/tv_discuss"android:text="商家"android:textColor="@color/dark_gray"/><TextViewandroid:layout_width="70dp"android:layout_height="30dp"android:layout_alignParentRight="true"android:layout_marginRight="15dp"android:background="@drawable/friend_list"android:gravity="center"android:text="好友拼单"android:textColor="#ef842c"android:textSize="12sp"/></RelativeLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><fragmentandroid:id="@+id/left"android:name="cn.itcast.menu.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"tools:layout="@layout/left_layout"/><fragmentandroid:id="@+id/right"android:name="cn.itcast.menu.RightFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"tools:layout="@layout/right_layout"/></LinearLayout></LinearLayout>

menu\FoodBean.java

封装菜品信息的实体类
package cn.itcast.menu;import java.io.Serializable;publicclassFoodBeanimplementsSerializable{//序列化时保持FoodBean类版本的兼容性privatestaticfinallong serialVersionUID =1L;private String name;//菜品名称private String sales;//月售信息private String price;//菜品价格privateint img;//菜品图片public String getName(){return name;}publicvoidsetName(String name){this.name = name;}public String getSales(){return sales;}publicvoidsetSales(String sales){this.sales = sales;}public String getPrice(){return price;}publicvoidsetPrice(String price){this.price = price;}publicintgetImg(){return img;}publicvoidsetImg(int img){this.img = img;}}

menu\LeftFragment.java

加载左侧菜单栏界面布局
package cn.itcast.menu;import android.app.Fragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;publicclassLeftFragmentextendsFragment{@OverridepublicvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState){
        View view =inflater.inflate(R.layout.left_layout,container,false);return view;}@OverridepublicvoidonPause(){super.onPause();}}

menu\RightAdapter.java

编写菜单列表的适配器
package cn.itcast.menu;import android.content.Context;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;publicclassRightAdapterextendsBaseAdapter{private Context mContext;private List<FoodBean> list;publicRightAdapter(Context context ,List<FoodBean> list){this.mContext = context;this.list=list;}@OverridepublicintgetCount(){//获取列表条目的总数return list.size();//返回ListView 条目的总数}@Overridepublic Object getItem(int position){return list.get(position);//返回列表条目的数据对象}@OverridepubliclonggetItemId(int position){return position;//返回列表条目的id}@Overridepublic View getView(int position, View convertView, ViewGroup parent){
        ViewHolder holder = null;if(convertView == null){
            convertView = View.inflate(mContext, R.layout.list_item, null);
            holder =newViewHolder();
            holder.tv_name =  convertView.findViewById(R.id.tv_name);
            holder.tv_sale =  convertView.findViewById(R.id.tv_sale);
            holder.tv_price =  convertView.findViewById(R.id.tv_price);
            holder.iv_img =  convertView.findViewById(R.id.iv_img);
            convertView.setTag(holder);}else{
            holder =(ViewHolder) convertView.getTag();}
        FoodBean bean=list.get(position);
        holder.tv_name.setText(bean.getName());
        holder.tv_sale.setText(bean.getSales());
        holder.tv_price.setText(bean.getPrice());
        holder.iv_img.setBackgroundResource(bean.getImg());return convertView;}classViewHolder{
        TextView tv_name, tv_sale,tv_price;
        ImageView iv_img;}}

menu\RightFragment.java

加载右侧菜单栏界面布局
package cn.itcast.menu;import android.app.Fragment;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ListView;import java.io.Serializable;import java.util.List;publicclassRightFragmentextendsFragment{private ListView lv_list;publicRightFragment(){}public RightFragment getInstance(List<FoodBean> list){
        RightFragment rightFragment =newRightFragment();//通过Bundle对象传递数据可以保证在设备横竖屏切换时传递的数据不丢失
        Bundle bundle =newBundle();//将需要传递的字符串以键值对的形式传入bundle对象
        bundle.putSerializable("list",(Serializable) list);
        rightFragment.setArguments(bundle);return rightFragment;}@OverridepublicvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState){
        View view = inflater.inflate(R.layout.right_layout, container,false);
        lv_list = view.findViewById(R.id.lv_list);if(getArguments()!= null){
            List<FoodBean> list =(List<FoodBean>)getArguments().getSerializable("list");
            RightAdapter adapter =newRightAdapter(getActivity(), list);
            lv_list.setAdapter(adapter);}return view;}}

menu\MainActivity.java

实现显示菜单的效果
package cn.itcast.menu;import android.app.FragmentManager;import android.app.FragmentTransaction;import android.graphics.Color;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.TextView;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;publicclassMainActivityextendsAppCompatActivity{private FragmentManager fragmentManager;private FragmentTransaction fragmentTransaction;private LeftFragment leftFragment;private TextView tv_recommend, tv_must_buy;private RightFragment rightFragment;//推荐菜单列表数据private String[] names1 ={"爆款*肥牛鱼豆腐骨肉相连三荤五素一份米饭","豪华双人套餐","【热销】双人套餐(含两份米饭)"};private String[] sales1 ={"月售520 好评度80%","月售184 好评度68%","月售114 好评度60%"};private String[] prices1 ={"¥23","¥41","¥32"};privateint[] imgs1 ={R.drawable.recom_one, R.drawable.recom_two,
            R.drawable.recom_three};//进店必买菜单列表数据private String[] names2 ={"'蔬菜主义'1人套餐","2人经典套餐","3人经典套餐"};private String[] sales2 ={"月售26 好评度70%","月售12 好评度50%","月售4 好评度40%"};private String[] prices2 ={"¥44","¥132","¥180"};privateint[] imgs2 ={R.drawable.must_buy_one, R.drawable.must_buy_two,
            R.drawable.must_buy_three};private Map<String,List<FoodBean>> map;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setData();init();clickEvent();}privatevoidinit(){
        fragmentManager =getFragmentManager();//获取fragmentManager//通过findFragmentById()方法获取leftFragment
        leftFragment =(LeftFragment) fragmentManager.findFragmentById(R.id.left);//获取左侧菜单栏中的控件
        tv_recommend = leftFragment.getView().findViewById(R.id.tv_recommend);
        tv_must_buy = leftFragment.getView().findViewById(R.id.tv_must_buy);}privatevoidsetData(){
        map=newHashMap<>();
        List<FoodBean> list1=newArrayList<>();
        List<FoodBean> list2=newArrayList<>();for(int i=0;i<names1.length;i++){
            FoodBean bean=newFoodBean();
            bean.setName(names1[i]);
            bean.setSales(sales1[i]);
            bean.setPrice(prices1[i]);
            bean.setImg(imgs1[i]);
            list1.add(bean);}
        map.put("1",list1);//将推荐菜单列表的数据添加到map集合中for(int i=0;i<names2.length;i++){
            FoodBean bean=newFoodBean();
            bean.setName(names2[i]);
            bean.setSales(sales2[i]);
            bean.setPrice(prices2[i]);
            bean.setImg(imgs2[i]);
            list2.add(bean);}
        map.put("2",list2);//将进店必买菜单列表的数据添加到map集合中}privatevoidclickEvent(){
        tv_recommend.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View v){//调用switchData()方法填充Rightfragment中的数据switchData(map.get("1"));
                tv_recommend.setBackgroundColor(Color.WHITE);
                tv_must_buy.setBackgroundResource(R.color.gray);}});
        tv_must_buy.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View v){switchData(map.get("2"));
                tv_must_buy.setBackgroundColor(Color.WHITE);
                tv_recommend.setBackgroundResource(R.color.gray);}});//设置首次进入界面后,默认需要显示的数据switchData(map.get("1"));}/**
     * 填充Activity右侧的Fragment,并传递列表数据list
     */publicvoidswitchData(List<FoodBean> list){
        fragmentManager =getFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();//开启一个事务//通过调用getInstance()方法实例化RightFragment
        rightFragment =newRightFragment().getInstance(list);//调用replace()方法
        fragmentTransaction.replace(R.id.right, rightFragment);
        fragmentTransaction.commit();}}

本文转载自: https://blog.csdn.net/weixin_46227276/article/details/123190185
版权归原作者 一条大蟒蛇6666 所有, 如有侵权,请联系我们删除。

“CH4-程序活动单元Activity”的评论:

还没有评论