Android应用程序开发技术 课件 第5章 UI进阶_第1页
Android应用程序开发技术 课件 第5章 UI进阶_第2页
Android应用程序开发技术 课件 第5章 UI进阶_第3页
Android应用程序开发技术 课件 第5章 UI进阶_第4页
Android应用程序开发技术 课件 第5章 UI进阶_第5页
已阅读5页,还剩128页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章UI进阶Android应用程序开发技术第四章介绍了Activity对应的各种布局以及布局中与用户进行交互的常用组件。在本章中介绍AndroidAPPUI开发中的一些实用技术,包括Fragment、菜单、工具和一些高级组件。通过这些技术的应用可以更加灵活方便的进行程序界面开发以及用户交互。项目导学5.1Fragment 5.2菜单5.3高级组件5.4本章总结5.5习题5.6上机内容安排5.1Fragment 5.2菜单5.3高级组件5.4本章总结5.5习题5.6上机内容安排Fragment是为了适应在大屏幕的平板电脑上进行UI设计,在Andorid3.0以后开始引入的一个API。可以想象,如果一个很大的界面,只用一个布局并且组件比较多,那么设计和管理都比较麻烦。Fragment又称为片段,利用Fragment我们可以根据需求对屏幕空间划分成几块,然后进行模块化管理,同时可以在程序运行的过程中动态的更新Activity的用户界面,这样可以极大的提高编程的灵活性。5.1Fragment

5.1.1Fragment简介

实际上,Fragment在手机界面开发中也是经常用到的,Fragment在UI设计上很好的实现了代码重用。在平板和手机界面中的布局和行为的差异如图5-1(a)和(b)所示。(a)平板布局(b)手机布局图5-1Fragment在不同设备上的使用图5-1(a)是程序运行在屏幕空间大的平板电脑上,在一个Activity中包含FragmentA和FragmentB两个片段,左边的FragmentA显示一个商品的分类列表,当单击一类商品时,右边会在FragmentB中显示对应的商品详情,这里FragmentA和FragmentB可以位于同一个ActivityA中;图(b)是程序运行在屏幕空间小的手机上,商品列表和商品详情无法在一个屏幕上显示,因此FragmentA和FragmentB分别放在ActivityA和ActivityB中,在用户单击FragmentA的商品分类的某一项时,它需要启动ActivityB来显示商品详情。5.1.1Fragment简介

(a)平板布局(b)手机布局图5-1Fragment在不同设备上的使用从图5-1我们可以知道,不同的设备在使用时布局可能不同,而且应用程序还应当能够根据不同的设备提供不同行为,也就是需要运行不同的Java代码。Fragment可以在不同屏幕间重用,例如图5-1中可以使用FragmentA实现商品列表,使用FragmentB显示商品详情。FragmentA和FragmentB可以被不同的布局共享,因此Fragment实际上实现了代码的重用。使用布局可以实现根据不同的环境有不同的用户界面和行为。5.1.1Fragment简介

(a)平板布局(b)手机布局图5-1Fragment在不同设备上的使用Fragment具有一定的独立型,可以认为是一个子Activity,它具有如下特点:1.Fragment具有生命周期。这体现在两个方面:可以在一个Activity中组合使用多个Fragment,构成一个多窗口的界面;同时可以在多个Activity中重复使用同一个Fragment。Fragment的使用使得UI设计更加灵活,可以将Fragment看作是Activity的模块,在Activity运行过程中可以动态的增加或移除某些Fragment。2.Fragment必须委托在Activity中才能运行。Fragment的生命周期受其宿主Activity的影响。Activity生命周期处于暂停、销毁和结束时,Fragment的生命周期也对应暂停、销毁和结束。5.1.1Fragment简介

5.1.2Fragment的生命周期

Fragment扩展自AndroidFragment类,这个类允许访问Fragment访问其生命周期方法。Fragment的生命周期和Activity的生命周期很类似,但由于Fragment是依赖于Activity而存在,因此需要与宿主Activity的生命周期交互。图5-2所示是Fragment的生命周期方法,并说明这些方法对应的Activity的状态。图5-2中所示的Fragment生命周期回调方法会在应用程序的执行时自动被Android系统调用,回调的情况如表5-1所示。图5-2Fragment的回调方法与Activity状态的对应关系序号回调方法系统回调的情况1onAttach()当Fragment被添加到它所在的Context时被回调。(仅回调1次)2onCreate()创建Fragment时被回调。(仅回调1次)3onCreateView()每次创建、绘制该Fragment的布局时被调用,该方法返回一个View组件。4onActivityCreate()当Fragment所在的Activity启动完成后会调用该方法。5onStart()启动Fragment时被回调,使Fragment让用户可见。6onResume()恢复Fragment时会被回调,在onStart()方法后一定会回调该方法,Fragment位于前台,且获得焦点。7onPause()暂停Fragment时被回调。Fragment依然可见,但是不能获得焦点。8onStop()有组件被遮挡,或者宿主Activity对象转为onStop时回调。Fragment不可见,且失去焦点。9onDestroyView()Fragment对象清理View资源时调用,即移除Fragment中的视图。10onDestroy()Fragment对象完成对象清理View资源时调用。(仅回调1次)11onDetach()与onAttach相对应,Fragment和Activity解除关联时调用。表5-1Fragment生命周期回调函数开发Fragment程序时,可以像开发Activity一样,根据需要选择性的重写指定的回调方法。Fragment中最常见的就是重写onCreateView()方法,该方法返回Fragment的View给所在的宿主Activity,显示Fragment的视图。使用Fragment编程时开发者可以根据需要重写Fragment的任意回调方法,通常会重写onCreate()、onCreateView()和onPause()这三个方法。最常用的是onCreateView()方法,在该方法返回的View是该Fragment所对应显示View,当Fragment绘制界面组件时会回调该方法。5.1.2Fragment的生命周期

5.1.3使用Fragment

在程序中有两种加载Fragment的方式,分别是静态加载和动态加载。静态加载是指将Fragment作为一个视图固定的放在Activity中,动态加载是指在程序运行的时候根据需要在Activity中动态的加载或切换Fragment。1.静态加载Fragment静态加载方式就是在Activity布局中,直接指定其所包含具体的Fragment类。静态加载Fragment的步骤如下:1)在工程中创建一个Fragment;(1)修改Fragment的布局文件;(2)更新Fragment类2)在Activity的布局文件中加载Fragment类;3)Activity类中的onCreate()方法中加载布局。【例5-1】静态加载Fragment。在如图5-3所示的运行图中,图5-3(a)是程序运行后的初始状态,显示的矩形框包含的是一个以静态方式加载的Fragment,该Fragment包含一个TextView和一个Button组件,当单击Fragment的命令按钮后,改变Fragment中TextView的文本,如图5-3(b)所示。(a)程序运行后初始状态(b)改变Fragment中TextView的文本图5-3例5-1静态Fragment加载举例5.1.3使用Fragment

创建一个名为fragmentfirst的工程,其中包含活动MainActivity的工程,MainActivity对应的布局文件为activity_main.xml;向工程中增加一个Fragment。在AndroidStudio左侧的浏览器工程视图显示方式切换到“Android”,选中app/java/包名.fragmentfirst,单击鼠标右键选择New->Fragment->Fragment(Blank),并为Fragment类和及其布局分别命名为BlankFragment1和fragment_blank1,点击Finish。系统会自动生成Fragment对应的Java代码文件和布局文件。5.1.3使用Fragment

系统自动生成的Fragment的布局与活动的布局看上去很类似,修改fragment_blank1.xml布局文件,定义一个TextView和Button组件,各组件属性设置如下所示。<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".BlankFragment1"><!--TODO:Updateblankfragmentlayout--><TextView5.1.3使用Fragment

android:id="@+id/TextView1"android:layout_width="match_parent"android:layout_height="40dp"android:text="FragmentTest!"/><Buttonandroid:id="@+id/btn"android:layout_width="match_parent"android:layout_height="40dp"android:text="FragmentHowareyou!"/></LinearLayout>系统自动生成的BlankFragment1是Fragment类的子类,这里需要修改BlankFragment1.Java代码,为其布局中的Button组件添加监听器,并重写单击方法,完整的代码如下所示。packagexsyu.jsj.fragmentfirst;importandroid.os.Bundle;importandroidx.fragment.app.Fragment;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.Button;importandroid.widget.TextView;/***Asimple{@linkFragment}subclass.*Usethe{@linkBlankFragment1#newInstance}factorymethodto*createaninstanceofthisfragment.*/5.1.3使用Fragment

publicclassBlankFragment1extendsFragment{

//TODO:Renameparameterarguments,choosenamesthatmatch//thefragmentinitializationparameters,e.g.ARG_ITEM_NUMBERprivatestaticfinalStringARG_PARAM1="param1";privatestaticfinalStringARG_PARAM2="param2";

//TODO:RenameandchangetypesofparametersprivateStringmParam1;privateStringmParam2;privateViewroot;privateTextViewtestview;privateButtonbutton;publicBlankFragment1(){//Requiredemptypublicconstructor}/***Usethisfactorymethodtocreateanewinstanceof*thisfragmentusingtheprovidedparameters.**@paramparam1Parameter1.*@paramparam2Parameter2.*@returnAnewinstanceoffragmentBlankFragment1.*/5.1.3使用Fragment

//TODO:RenameandchangetypesandnumberofparameterspublicstaticBlankFragment1newInstance(Stringparam1,Stringparam2){BlankFragment1fragment=newBlankFragment1();Bundleargs=newBundle();args.putString(ARG_PARAM1,param1);args.putString(ARG_PARAM2,param2);fragment.setArguments(args);returnfragment;}

@OverridepublicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);if(getArguments()!=null){mParam1=getArguments().getString(ARG_PARAM1);mParam2=getArguments().getString(ARG_PARAM2);}}

@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){//Inflatethelayoutforthisfragmentif(root==null){root=inflater.inflate(R.layout.fragment_blank1,container,false);5.1.3使用Fragment

}testview=root.findViewById(R.id.TextView1);button=root.findViewById(R.id.btn);button.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){testview.setText("I'mfine,andyou?");}});returnroot;}}对以上代码做几点说明:inflater.inflate()方法加载Fragment的布局文件,该方法指明BlankFragment1类对应的布局资源是fragment_blank1。从这里可以看出,Fragment对其布局的解析位置不同,Fragment是在onCreateView()中指明其对应的布局,而Activity则是在onCreate()中指明其布局的。在Activity的布局中加载Fragment类。在MainActivity的布局文件activity_main.xml中增加了一个<fragment>元素,其作用是在活动布局中为Fragment的对应布局“占位”,<fragment>元素是一个视图,这个视图是由name属性特指的Fragment类对应的布局。在下面所示activity_main.xml的布局代码中,定义了一个<fragment>元素,其属性android:name="xsyu.jsj.fragmentfirst.BlankFragment1"指明了Fragment类的完全限定名是"xsyu.jsj.fragmentfirst.BlankFragment1",Android在创建活动的布局时,会把这个<fragment>替换为xsyu.jsj.fragmentfirst包中一个View对象,这个View对象是步骤2介绍的由BlankFragment1类的onCreateView()方法返回的View对象。需要说明的是,<fragment>元素必须为其指定android:id属性。5.1.3使用Fragment

<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="MainActivity!"android:id="@+id/TextView1"/>

<fragmentandroid:name="xsyu.jsj.fragmentfirst.BlankFragment1"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:id="@+id/fragment1"/></LinearLayout>5.1.3使用Fragment

Activity加载布局。系统生成的MainActivity.java在onCreate()中会自动调用setContentView(R.layout.activity_main)方法加载自身的布局。由于该布局中包含了<fragment>元素,会自动替换为<fragment>元素的name属性对应Fragment类返回的View。【例5-1】中是BlankFragment1的onCreateView()方法返回的View,是与fragment_blank1.xml对应的视图。5.1.3使用Fragment

(a)程序运行后初始状态(b)改变Fragment中TextView的文本图5-3例5-1静态Fragment加载举例程序界面如图5-3(a)所示。点击其中的Button后会将Fragment中的TextView组件的提示文本更新为“I'mfine,andyou?”。静态加载Fragment是将Fragment添加到Activity的布局文件中,使Fragment及其视图与Activity的视图绑定在一起,在Activity的生命周期中无法实现灵活的切换Fragment视图。因此实际的开发中Fragment常采用动态加载的方式。5.1.3使用Fragment

图5-3(a)程序运行后初始状态2.动态加载Fragment在运行时根据用户需要添加、删除和替换Fragment是动态加载Fragment的基本操作。在Android中Fragment的动态加载是通过FramgmentManager实现的,FragmentManager类负责在应用中对Fragment执行添加、删除、替换等操作,或者将其添加到堆栈或从堆栈弹出等。因此,对FramgmentManager可以看作是Activity和Fragment之间的桥梁。Activity通过FragmentManeger实现对Fragment的所有操作。FragmentManager对Activity视图中Fragment的每一次改变,如添加、删除、替换等,都称为一个事务FragmentTransaction,FragmentTransaction表示Activity对Fragment的执行的多个改变,这些改变必须进行提交。5.1.3使用Fragment

因此,在Activity中对Fragment操作需要执行如下的链式操作:步骤1:通过getFragmentManage()方法获得FragmentManager对象。在每个FragmentActivity及其子类(如AppCompatActivity)都可以通过getSupportFragmentManager()方法访问FragmentManager对象。步骤2:获得FragmentTransation对象,使FragmentManager开启一个事务。在布局容器中显示Fragment时,需要通过使用FragmentManager的beginTransaction()方法创建FragmentTransaction对象。5.1.3使用Fragment

步骤3:在事务中添加操作。Fragment的事务,就是对Activity中Fragment的操作,可以通过调用表5-2中列出的FragmentTransaction的方法实现。方法名操作add()向Activity中添加一个Fragmentreplace()替换Activity中Fragmentremove()删除Activity中Fragmentshow()在Activity中显示Fragmenthide()隐藏Activity中FragmentaddToBackTrack()把本次事物的所有操作在压入堆栈中popbackTrack将回退栈中的最近的一次事务弹出表5-2Fragment的事务5.1.3使用Fragment

步骤4:提交事务到主线程执行事务。提交事务是通过执行FragmentTmit()

方法实现的。例如,下面代码中在获得FragmentManager和FragmentTransaction后,用replace方法将Activity布局中的id=R.id.fragment_Dynamic的组件替换为名为fragment对应的Fragment,然后提交。FragmentManagerfragmentManager=getSupportFragmentManager();FragmentTransactiontransaction=fragmentManager.beginTransaction();transaction.replace(R.id.fragment_Dynamic,fragment);mit();5.1.3使用Fragment

【例5-2】动态加载Fragment举例。在如图5-4所示的运行图中,主Activity的布局activity_main.xml中左侧有两个按钮,右侧的区域是放置Fragment视图的区域。程序运行单击两个按钮时,会分别加载fragment_1.xml和fragment_2.xml片段。图5-4中实现的是单击btn1(“加载片段1”)按钮后的显示结果。图5-4动态加载Fragment举例5.1.3使用Fragment

操作步骤如下:创建一个名为fragment_dynamic的工程,其中包含活动名MainActivity的工程,MainActivity对应的布局文件为activity_main.xml,将其代码修改如下。布局中的水平线性布局分为左右两部分,左边是一个垂直线性布局,包含两个Button。水平布局的右侧是一个用于显示Fragment的FrameLayout。<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"5.1.3使用Fragment

android:layout_height="match_parent"android:orientation="horizontal"tools:context=".MainActivity">

<LinearLayoutandroid:layout_width="100dp"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:id="@+id/btn1"android:layout_width="match_parent"android:layout_height="40dp"android:text="加载片段1"/>

<Buttonandroid:id="@+id/btn2"android:layout_width="match_parent"android:layout_height="40dp"android:text="加载片段2"/></LinearLayout>

<FrameLayoutandroid:id="@+id/fragment_Dynamic"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"/>

</LinearLayout>5.1.3使用Fragment

向工程中增加两个Fragment。为了实现动态加载两个Fragment功能,新建两个Fragment(Blank),对应的Fragment类和布局文件名如表5-3所示。表5-3【例5-1】的两个Fragment文件类名布局文件名包含的组件其它属性设置Fragment1fragment_1.xml1个TextView布局背景色红色(#ff0000)Framgment2fragment_2.xml1个TextView布局背景色紫色(#ff00ff)5.1.3使用Fragment

fragment_1.xml文件的代码如下所示,fragment_2.xml代码与fragment_1.xml的代码类似,差别只是布局的背景色和TextView的text的属性="NowinFramgment2",TextView的text属性分别用中文或英文提示当前所加载的Fragment的名称。5.1.3使用Fragment

<?xmlversion="1.0"encoding="utf-8"?><FrameLayoutxmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ff0000"tools:context=".Fragment1">

<!--TODO:Updateblankfragmentlayout--><TextViewandroid:layout_width="match_parent"android:layout_height="40dp"android:id="@+id/textview1"android:text="你好,片段1已加载!"/></FrameLayout>在Activity类的MainActivity.java代码中动态加载两个Fragment。Activity是通过布局中的两个Button组件单击动作实现Fragment的动态加载,因此MainActivity类编程实现的主要功能是:1)为Activity类中的两个Button组件设置监听器为MainActivity类自身。5.1.3使用Fragment

protectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btn1=findViewById(R.id.btn1);btn2=findViewById(R.id.btn2);btn1.setOnClickListener(this);btn2.setOnClickListener(this);}2)MainActivity类实现View.OnClickListener接口的onClick(Viewv)MainActivity类定义的语句中声明实现View.OnClickListener接口,并在该类中实现了该接口的onClick(Viewv)方法。publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{…@OverridepublicvoidonClick(Viewv){…}5.1.3使用Fragment

在onClick()方法中根据Button组件的id分别加载片段Fragment1和Fragment2。代码中的DynamicRepalceFragment()方法用于加载参数指定的片段。@OverridepublicvoidonClick(Viewv){switch(v.getId()){caseR.id.btn1:DynamicRepalceFragment(newFragment1());break;caseR.id.btn2:DynamicRepalceFragment(newFragment2());break;}}5.1.3使用Fragment

3)片段的动态加载方法DynamicRepalceFragment()DynamicRepalceFragment()方法完成对两个Fragment的动态加载,因此这里介绍android中对Fragment管理和事务的概念。5.1.3使用Fragment

Activity对Fragment的管理是依靠Fragment的管理类FragmentManager进行的,FragmentManager可以通过getSupportFragmentManager()获取。FragmentManager可以完成对Fragment在如下几个方面的管理:获取指定的Fragment:使用findFragmentById()或findFragmentByTag();对Fragment实现后台栈的进栈或出栈管理,调用popBackStack()将Fragment从后台栈中弹出,调用addToBackStack(Null)将Fragment压入后台栈;监听后台栈变化:通过注册addOnBackStackChangeListener()一个监听器实现。Activity对Fragment执行的改变操作,如添加,删除,替换Fragment等,需要借助于FragmentTransation对象,FragmentTransation也称Fragment事务。可以通过FragmentManager的beginTransaction()方法开启一个FragmentTransaction事务,FragmentTransaction代表Activity对Fragment执行多个改变,可通过FragmentManager来获得FragmentTransaction,每个FragmentTransaction可以包含调用多个add(),remove(),和replace()操作,最后必须调用commit()方法提交事务。5.1.3使用Fragment

将主Activity中id为fragment_Dynamic的Fragment替换为参数fragment指示的片段,就实现了动态加载。5.1.3使用Fragment

privatevoidDynamicRepalceFragment(Fragmentfragment){FragmentManagerfragmentManager=getSupportFragmentManager();FragmentTransactiontransaction=fragmentManager.beginTransaction();transaction.replace(R.id.fragment_Dynamic,fragment);mit();}其中transaction.replace(R.id.fragment_Dynamic,fragment);将主Activity中id为fragment_Dynamic的Fragment替换为参数fragment指示的片段,实现了动态加载。MainActivity.java的完整代码如下。Fragment获得Activity中的组件可以通过。packagexsyu.jsj.dynamic_fragment;importandroidx.appcompat.app.AppCompatActivity;importandroidx.fragment.app.Fragment;importandroidx.fragment.app.FragmentManager;importandroidx.fragment.app.FragmentTransaction;

importandroid.os.Bundle;importandroid.text.style.DynamicDrawableSpan;importandroid.view.View;5.1.3使用Fragment

importandroid.widget.Button;

publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener{privateButtonbtn1,btn2;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);btn1=findViewById(R.id.btn1);btn2=findViewById(R.id.btn2);btn1.setOnClickListener(this);btn2.setOnClickListener(this);}@OverridepublicvoidonClick(Viewv){switch(v.getId()){caseR.id.btn1:DynamicRepalceFragment(newFragment1());break;caseR.id.btn2:DynamicRepalceFragment(newFragment2());break;}}//动态添加FragmentprivatevoidDynamicRepalceFragment(Fragmentfragment){FragmentManagerfragmentManager=getSupportFragmentManager();FragmentTransactiontransaction=fragmentManager.beginTransaction();transaction.replace(R.id.fragment_Dynamic,fragment);mit();}}5.1.3使用Fragment

5.1.4Fragment与Activity通信Fragment和Activity是两个独立的类,两者都具有与用户交互的功能。Fragment是依存于Activity的,因此两者之间一定存在通信,也就是数据交换。将两者之间的通信分成以下三种情况:从Activity向Fragment传送数据;从Fragment向Activity传输数据;Fragment之间传送数据;除了信息传递之外,Fragment和Activity也可以访问对方的组件。Fragment通过getActivity().findViewById(R.id.list)方法获得Activity中的组件;Activity通过getFragmentManager.findFragmentByid(R.id.fragment1)方法获得Fragment中的组件;5.1.4Fragment与Activity通信下面我们对Fragment和Activity之间的三种数据传递方式分别进行说明。1.从Activity向Fragment传送数据Activitiy向Fragment传送数据可以采用Bundle类实现。在Activity中需要做如下操作:在Activity中创建bundle对象;利用bundle的各种putxx()向bundle中写入待传数据;用Fragment对象的setArguments(bundle)将bundle传递给Fragment。Fragment获取Activity的传入数据步骤如下:利用getArguments()获取bundle对象;

利用bundle的getxx()获取传入的数据。下面,我们按照这个步骤,在【例5-2】代码的基础上,实现从MainActivity向Fragment1中传送字符串,并在文本框TextView1中显示该字符串。对MainActivity.java中的代码onClick()做如下改动:@OverridepublicvoidonClick(Viewv){switch(v.getId()){caseR.id.btn1:Bundlebundle=newBundle();bundle.putString("info","这是从Activity传递的信息");Fragment1fg=newFragment1();fg.setArguments(bundle);DynamicRepalceFragment(fg);break;caseR.id.btn2:DynamicRepalceFragment(newFragment2());break;}5.1.4Fragment与Activity通信在Fragment1.java获取Bundle传入的数据,并在文本框中显示,修改的代码如下:@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){//Inflatethelayoutforthisfragmentif(root==null)root=inflater.inflate(R.layout.fragment_1,container,false);textview1=root.findViewById(R.id.textview1);Bundlebundle=this.getArguments();Stringstr=bundle.getString("info");textview1.setText(str);returnroot;}5.1.4Fragment与Activity通信2.从Fragment向Activity传输数据Fragment向Activity传输数据的最常用方式是利用接口。接口实际上就是给出了一个对象和另一个对象有效交互的最低需求。这样片段就可以实现与指定接口的任意活动进行交互。接口在两者之间的作用如图5-5所示。从图中Activity和Fragment是利用接口Listener进行信息传递。从图5-5中可以看出Activity必须声明实现接口,且实现该接口的所有方法。在Fragment中需要定义一个接口对象,并将该对象指向其所在的Activity引用,然后通过该引用调用Activity的接口方法。图5-5通过接口实现从Fragment向Activity传输数据示意图5.1.4Fragment与Activity通信(a)数据传送前(a)数据传送前图5-6【例5-3】运行效果图5.1.4Fragment与Activity通信【例5-3】从Fragment向Activity传输数据举例。图5-6是【例5-3】的运行结果。点击图5-6(a)中Fragment按钮,会传递一个字符串信息到Activity,并在Activity中显示。【例5-3】从Fragment向Activity传输数据举例。程序的设计过程如下。定义一个接口IFragmentCallBack。packagexsyu.jsj.fragmenttest;publicinterfaceIFragmentCallBack{voidsetMsgtoActivity(Stringmsg);StringgetMsgFromActivity(Stringmsg);}在Fragment中定义接口对象fragmentcallBack并在onAttach()对其初始化。@OverridepublicvoidonAttach(@NonNullContextcontext){super.onAttach(context);this.fragmentCallBack=(IFragmentCallBack)context;}5.1.4Fragment与Activity通信为了演示参数传递,在Fragment中定义一个Btn,用于向Activity传输数据。<Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/frgbtn1"android:layout_gravity="center“android:text="数据传递演示"/>改写Fragment中的onCreateView(),且实现Btn的消息处理函数,在Btn的onClick()中调用Activity实现的IFragmentCallBack接口方法。@Override@Override5.1.4Fragment与Activity通信publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){//Inflatethelayoutforthisfragmentif(rootView==null)rootView=inflater.inflate(R.layout.fragment_blank1,container,false);btn=(Button)rootView.findViewById(R.id.frgbtn1);btn.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){fragmentCallBack.setMsgtoActivity("Hello,AMessagefromFragment");3.Fragment之间传送数据当一个Fragment被另一个Fragment替换时,两个Fragment之间可能会有数据传输。Fragment之间的数据传送比较简单,只要找到需要接受数据的fragment对象,直接调用setArguments()实现数据传送。被替换Fragment将数据传入新的Fragment,新的Fragment在创建后通过getArguments()方法获取传入的数据。5.1.4Fragment与Activity通信例如有两个Fragment,分别是Fragment1和Fragment2。Fragment1需要将一个字符串数据(“从Fragment1传来的参数”)传递给Fragment2。具体步骤如下:1)Fragment2新建一个方法用于参数传入在Fragment2新建一个newInstance()方法,在该方法中新建一个Fragment2实例,然后将参数通过setArguments()实现数据保存。publicstaticFragment2newInstance(Stringtext){Fragment2fragment=newFragment2();Bundleargs=newBundle();args.putString("param",text);fragment.setArguments(args);returnfragment;}5.1.4Fragment与Activity通信2)在Fragment1中创建Fragment2并传递参数在Fragment1中,点击Button按钮组件(id=load_fragment2_btn),加载Fragment2。在Fragment1的onCreateView()代码中,通过调用Fragment2的newInstance()来创建实例并传递参数:@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){//InflatethelayoutforthisfragmentViewview=inflater.inflate(R.layout.fragment_1,container,false);Buttonbtn=(Button)view.findViewById(R.id.load_fragment2_btn);btn.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(finalViewview){Fragment2fragment2=Fragment2.newInstance("从Fragment1传来的参数");FragmentTransactiontransaction=getFragmentManager().beginTransaction();transaction.add(R.id.main_layout,fragment2);5.1.4Fragment与Activity通信transaction.addToBackStack(null);mit();}});returnview;}}publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){//InflatethelayoutforthisfragmentViewview=inflater.inflate(R.layout.fragment_2,container,false);

if(getArguments()!=null){StringmParam1=getArguments().getString("param");TextViewtv=(TextView)view.findViewById(R.id.textview);tv.setText(mParam1);}returnview;}3)Fragment2获取传入的参数Fragment2在执行OnCreateView()方法中通过getArguments()中获取出传入的参数并在文本框TextView中显示,代码如下。5.1.4Fragment与Activity通信5.1Fragment

5.2菜单5.3高级组件5.4本章总结5.5习题5.6上机内容安排5.2菜单

菜单虽然在手机中的应用相比桌面应用减少了许多,但是菜单在Android应用中还是常见且非常重要。在手机应用中菜单默认是不可见的,只有当用户在特定区域或长按某些组件时才会显示关联的菜单。从应用的角度可以把菜单分为三类,分别是选项菜单(OptionsMenu)、上下文菜单(ContextMenu)、弹出菜单(PopupMenu)。这几种菜单的区别如下:OptionMenu:选项菜单是Android中最常见的菜单,是在APP的顶部的ActionBar右上角出现的菜单。ContextMenu:上下文菜单,是通过长按某个视图组件后出现的浮动菜单。这个菜单是根据不同的上下文环境出现不同的选项,从本质说是该视图组件注册了上下文菜单。PopupMenu:弹出式菜单显示垂直的列表项,与上下文菜单不同的是,在特定区域点击任何一个组件都弹出相同的菜单,类似于一个弹窗。5.2.1选项菜单

选项菜单是Android中最常见的菜单,是在APP的顶部的标题栏,即ActionBar右上角出现的菜单。选项菜单的编程步骤如下:构建Menu资源文件;加载菜单资源;处理菜单项点击事件。5.2.1选项菜单

【例5-4】选项菜单应用举例。在一个APP中通过选项菜单中的三个选项,包括“设置”、“退出”和“帮助”。“设置”菜单实现TextView文本颜色的设置,“退出”菜单退出应用程序,“帮助”显示程序功能。创建一个工程Samp_Menu,建立的工程包含一个活动main_activity.java和一个布局activity_main.xml。按照步骤建立并实现选项菜单的功能。activity_main.xml中包含android:id="@+id/tvshow"的TextView组件。完整代码如下。<?xmlversion="1.0"encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity">

<TextViewandroid:id="@+id/tvshow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="HelloWorld!"android:textSize="20dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/>5.2.1选项菜单

1.构建Menu资源文件创建菜单的方式有两种:一种是直接通过编写菜单XML文件,然后调用getMenuInflater().inflate(R.menu.menu_main,menu)加载菜单;通过代码方式动态添加,onCreateOptionsMenu的参数menu,调用add方法添加菜单,该方法的常用原型为:publicabstractMenuItemadd(intgroupId,intitemId,intorder,CharSequencetitle)上面的两种方法中,方式(2)通过编码的方式添加菜单项比较灵活,但是这种方式代码冗长,不利于程序维护;而方式(1)的XML文件形式的菜单更利于维护,菜单项ID的创建和管理全部由Android系统来完成,开发人员不必自定义菜单的常量ID,而且程序代码的可读性更好,因此建议采用XML方式编写菜单。5.2.1选项菜单

2.生成XML菜单资源的方法:创建Menu资源的*.XML文件。在res目录点击右键—>androidResourceFile->将“Resourcetype"中选择资源类型为“Menu”,为菜单资源文件命名为“menu_option”,点击完成后会发现工程浏览器的在res目录生成了一个menu子目录并创建了一个menu_option.xml文件。在资源文件drawable目录下导入三个图标文件:5.2.1选项菜单

exit.png;help.png;settings.png。编辑menu_option.xml文件。要定义菜单,需在项目res/menu/目录内创建一个XML文件,并使用以下元素构建菜单:<menu>标签:定义Menu,即菜单项的容器。<menu>元素必须是该文件的根节点,并且能够包含一个或多个<item>和<group>元素。<item>标签:是菜单项,用于创建MenuItem。可能包含嵌套的<menu>元素,以便创建子菜单。5.2.1选项菜单

<item>标签中可以设置的常见属性如下:android:id:菜单项(MenuItem)的唯一标识;android:title:菜单项的标题(必选);android:icon:菜单项的图标(可选),需要显示的图标;android:showAsAction:指定菜单项的显示方式,多个属性值之间可以使用“|”隔开,参数取值及含义见表5-4。5.2.1选项菜单

5-4菜单显示方式参数及含义有效值描述ifRoom在空间足够时,菜单项会显示在ActionBar中,否则收纳入┆菜单中。always菜单项永远不会被收纳到溢出菜单中,因此在菜单项过多的情况下可能超出菜单

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论