使用Fragment创建动态用户界面
在Android上创建动态的并且多窗格的用户界面,你需要使用模块封装UI组件和Activity的行为,并且这些模块你可以将它们换入和换出你的Activity中。你可以使用Fragment类来创建这些模块,它表现的就像是嵌套的Activity,可以定义自己的布局并管理自己的生命周期。
当一个Fragment可以指定它自己的布局时,它也可以在一个Activity中和其他的Fragment组合在一起进行配置,从而为不同的屏幕大小修改你的布局配置(比如在小的屏幕上可能一次只显示一个Fragment,但在一个大的屏幕上可以显示两个或者更多)。
这个课程告诉你如何使用Fragment创建一个动态的用户体验并且为不同屏幕大小的设备优化你的app的用户体验。这些支持运行最老Android1.6版本系统的设备。
使用Android支持库
Android支持库提供一个带有API库的JAR文件,这些API库允许你的app运行在更早版本的Android上时,可以使用一些最近的Android API。举个例子,支持库提供了一个版本的Fragment API,使你可以使用Android1.6(API level 4)及以上版本才能使用的Fragment API。
这一课告诉你如何设置app来使用支持库,从而可以使用Fragment来创建动态app用户界面。
设置你的工程使用支持库
设置你的工程:
- 使用SDK Manager下载Android支持库
- 在你的Android工程的顶级层次创建一个libs目录
- 定位你想使用的库的jar文件,并将它拷贝到libs目录。举个例子,支持API level 4及以上版本的支持库是<sdk>/extras/android/support/v4/android-support-v4.jar
- 更新你的manifest文件,设置最小API级别为4,目标API级别为最新发布的版本。
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" />
导入支持库API
支持库包含大量的API,要么是最近版本Android增加的要么是在平台上完全不存在的,它们只是在你开发特殊的应用程序特性时提供额外的支持。
你可以在平台文档库(android.support.v4.*)中找到所有的API支持库的指导文档。
警告:为了确保你不会在老的系统版本上意外的使用新的API,请确定你是从android.supoort.v4.app包中导入Fragment类和相关的API。
import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; ...
当使用Android支持库时,创建一个使用Fragment的Activity类时,你必须继承FragmentActivity类而不是传统的Activity类,你将会在下一课看到一些关于Fragment和Activity的示例代码。
创建一个Fragment
你可以认为Fragment是Activity的一个单元段,它拥有自己的生命周期,接收它自己的输入事件,可以在Activity运行的时候被增加和删除(就像是一种子Activity,你可以在不同的Activity中重用它)。这一课将告诉你如何使用Android支持库继承Fragment类,因此你的app可以仍然兼容运行像Android1.6这么旧的系统的设备。
注意:如果你因为其他原因决定你的app要求的最低的API level为11的话,你就不需要使用Android支持库了,可以使用框架自带的Fragment类及相关的API。请注意这一课重点关注使用来自支持库的API,它使用一个特殊的包签名,并且有的时候API的名字也和平台自带的略有不同。
创建一个Fragment类
为了创建一个Fragment,需要继承Fragment类,然后重写一些关键的生命周期方法来插入你自己的app的逻辑,就类似你处理Activity类的方式。
当创建一个Fragment时,有一个不同是你必须使用onCreateView()回调函数来定义布局。实际上,这是你唯一需要的回调函数为了让一个Fragment运行。例如,这里有一个简单的指定自己的布局的Fragment:
import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.ViewGroup; public class ArticleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.article_view, container, false); } }
就像一个Activity,一个Fragment应该实现其他的生命周期方法,从而允许你管理它的状态随着它被从一个Activity增加或删除,就像Activity在它的生命周期状态之间转换一样。例如,当一个Activity的onPause()方法被调用,Activity中的每个Fragment都会收到一个onPause()回调。
更多的关于Fragment生命周期和回调方法的信息可以在Fragment开发者指南里获得。
通过XML将一个Fragment添加到Activity中
虽然Fragment是可重用的模块化的UI组件,但是每个Fragment实例必须和一个父组件FragmentActivity关联在一起。你可以通过在Activity的布局xml文件中定义每一个Fragment来达到这个关联的目录。
注意:FragmentActivity是一个在支持库中提供的特殊的Activity,来在版本低于API level 11的系统上支持Fragment。如果你支持的最低的系统版本是API level 11或更高,则你可以使用一个普通的Activity。
这里有一个布局文件的例子,当设备屏幕被认为是大的时候,它添加两个Fragment到Activity中(通过目录名的large限定词来指定)。
res/layout-large/news_articles.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <fragment android:name="com.example.android.fragments.HeadlinesFragment" android:id="@+id/headlines_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.android.fragments.ArticleFragment" android:id="@+id/article_fragment" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>
提示:如果需要获得更多的关于为不同屏幕大小创建布局文件的信息,请阅读支持不同屏幕大小章节
这里是一个Activity如何使用这个布局文件:
import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_articles); } }
注意:当你通过在XML布局文件中定义Fragment的方式将一个Fragment添加到一个Activity中时,你不能在运行时移除这个Fragment。如果你计划在用户交互过程中换入和换出你的Fragment,你必须在Activity首次启动时添加Fragment到Activity中,就像下一课所示。
创建一个灵活的用户界面
当设计你的应用程序使其支持大范围的屏幕大小时,你能在不同的布局配置中重用你的Fragment,从而在可用的屏幕空间的基础上优化用户体验。
举个例子,在手持设备上,每次只为单个窗格用户界面显示一个Fragment可能是合适的。相反的,你可能想要在平板上设置并排的Fragment从而向用户显示更多的信息,因为平板上有一个更宽的屏幕。
FragmentManager类提供方法允许你在运行时为Activity增加、移除和替换Fragment,从而可以创建一个动态的体验。
在运行时为Activity增加一个Fragment
与其在布局文件中为Activity定义Fragment,就像前面的课程展示的<fragment>元素一样,你可以在Activity运行期间为Activity增加Fragment。如果你计划在Activity的生命周期中更改Fragment的话,这很重要。
为了执行一个增加或移除Fragment的事务,你必须使用FragmentManager来创建一个FragmentTransaction,这个类提供API来增加、移除、替换和执行其他Fragment事务。
如果你的Activity允许Fragment被移除或替换的,你应该在Activity的onCreate()方法期间增加初始Fragment到这个Activity上。
处理Fragment时有一个重要的原则,尤其是那些你需要在运行增加的Fragment,那就是在布局中Fragment必须有一个容器视图,Fragment的布局将会在这个视图中。
下面这个布局是前面的课程中展示的一个可选布局,每次只展示一个Fragment。为了能够使用另一个Fragment替换这个,Activity的布局中包括一个空的FrameLayout用作Fragment的容器。
注意:这个文件的文件名和前一课中的布局文件是一样的,但是布局目录不包括large限定符,因此这个布局会在设备屏幕较小时使用,因为这个屏幕不能在同一时间安装两个Fragment。
/res/layout/news_articles.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" />
在你的Activity内部,通过支持库API调用getSupportFragmentManager()方法类获取一个FragmentManager。然后调用beginTransaction()方法来创建一个FragmentTransaction然后调用add()方法增加一个Fragment。
你可以使用同一个FragmentTransaction在一个Activity执行多个Fragment事务。当你准备好做出这些改变后,你必须执行commit()方法。
这里有一个例子,告诉你如何在前面的布局中增加一个Fragment。
import android.os.Bundle; import android.support.v4.app.FragmentActivity; public class MainActivity extends FragmentActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.news_articles); // Check that the activity is using the layout version with // the fragment_container FrameLayout if (findViewById(R.id.fragment_container) != null) { // However, if we're being restored from a previous state, // then we don't need to do anything and should return or else // we could end up with overlapping fragments. if (savedInstanceState != null) { return; } // Create an instance of ExampleFragment HeadlinesFragment firstFragment = new HeadlinesFragment(); // In case this activity was started with special instructions from an Intent, // pass the Intent's extras to the fragment as arguments firstFragment.setArguments(getIntent().getExtras()); // Add the fragment to the 'fragment_container' FrameLayout getSupportFragmentManager().beginTransaction() .add(R.id.fragment_container, firstFragment).commit(); } } }
因为这个Fragment是在运行时被增加到FrameLayout容器中的,而不是通过<fragment>元素定义在Activity的布局文件中的,因此Activity可以移除这个Fragment或使用另一个Fragment替换它。
使用另一个Fragment替换这个
替换一个Fragment的过程和增加一个很像,只是要求调用replace()方法,而不是add()方法。
始终在大脑中记住,当你执行Fragment事务时,比如替换或者删除一个Fragment,允许用户导航返回并撤销这个改变通常是合适的。为了允许用户通过Fragment事务导航回来,你必须在commit FragmentTransaction之前调用addToBackStack()方法。
注意:当你移除或替换一个Fragment并把这个事务添加到返回栈中时,移除的Fragment是被停止了(不是销毁)。如果用户导航回来恢复这个Fragment,它重新启动了。如果你没有将这个事务添加到返回栈中,则这个Fragment在被移除或替换时被销毁了。
这里有一个使用另一个Fragment替换的例子:
// Create fragment and give it an argument specifying the article it should show ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack so the user can navigate back transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit();
addBackStack()方法使用一个可选的字符串参数,用于为这个指定一个唯一的名字。这个名字不需要,除非你要使用FragmentManager.BackStackEntry API执行高级Fragment操作
和其他Fragment通信
为了重用Fragment UI组件,你应该将每个Fragment构建成完全独立的、模块化的组件,定义它们自己的布局和行为。一旦你已经定义好这些可重用的Fragment,你就能将它们和Activity关联在一起,并将它们和应用程序逻辑联系在一起从而实现完全合成的用户界面。
通常,你会想要一个Fragment和另一个通信,例如基于用户时间改变内容。所有的Fragment到Fragment之间的通信都是通过关联的Activity完成的。两个Fragment应该从不直接通信。
定义一个接口
为了让一个Fragment的通信取决于它的Activity,你可以在Fragment类中定义一个接口然后在Activity中实现它。Fragment在它的onAttach()声明周期方法期间获得这个接口的实现,从而可以通过调用接口方法来与Activity通信。
这里有一个Fragment同Activity通信的例子:
public class HeadlinesFragment extends ListFragment { OnHeadlineSelectedListener mCallback; // Container Activity must implement this interface public interface OnHeadlineSelectedListener { public void onArticleSelected(int position); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mCallback = (OnHeadlineSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnHeadlineSelectedListener"); } } ... }
现在Fragment可以通过使用OnHeadlineSelectedListener接口的mCallback实例调用onArticleSelected()方法(或者接口中的其他方法),发送消息给Activity。
例如,当用户点击一个列表项目时,Fragment中的如下方法被调用。Fragment使用回调接口来发布事件给父Activity。
@Override public void onListItemClick(ListView l, View v, int position, long id) { // Send the event to the host activity mCallback.onArticleSelected(position); }
实现接口
为了接收从Fragment过来的事件回调,作为Fragment的宿主的Activity必须实现Fragment类中定义的接口。
例如,下面这个Activity实现了上面例子中Fragment定义的接口:
public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article } }
发送消息给Fragment
宿主Activity使用findFragmentById()函数获取Fragment的实例后,可以直接调用Fragment的公共方法发送消息给Fragment。
举个例子,设想上面所示的Activity可能包含另一个Fragment用于显示上面的回调函数返回的数据所指定的列表项。在这种情况下,Activity可以传递在回调函数中收到的信息给另一个将要显示这个列表项的Fragment。
public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ... public void onArticleSelected(int position) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article ArticleFragment articleFrag = (ArticleFragment) getSupportFragmentManager().findFragmentById(R.id.article_fragment); if (articleFrag != null) { // If article frag is available, we're in two-pane layout... // Call a method in the ArticleFragment to update its content articleFrag.updateArticleView(position); } else { // Otherwise, we're in the one-pane layout and must swap frags... // Create fragment and give it an argument for the selected article ArticleFragment newFragment = new ArticleFragment(); Bundle args = new Bundle(); args.putInt(ArticleFragment.ARG_POSITION, position); newFragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack so the user can navigate back transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit(); } } }
相关推荐
Android Fragment是Android应用程序开发中的一个重要组件,它允许开发者在单个Activity中构建模块化的界面,增强了...通过熟练掌握Fragment的使用,你可以创建更加灵活、可复用的代码结构,提升应用程序的用户体验。
Fragment是一种基本组件,代表Activity中的一个行为或用户界面的一部分。您可以将多个Fragment组合到一个Activity中,建立一个多窗格UI,并重用一个Fragment在多个Activity中。 Fragment可以被认为是一个模块化的...
- **Activity与Fragment**:Activity代表应用的用户界面,Fragment是可嵌入到Activity中的可重用UI组件,它们共同构成了应用的视图层次。 2. **百度翻译API**: - **接入流程**:开发者需要在百度AI开放平台注册...
Fragment是Android用来构建动态用户界面的一个组件,它可以让你在一个Activity中添加、移除或替换UI部分而不需要重新启动Activity。这对于适应不同屏幕尺寸和设备形态的开发尤为重要。 在数据保存方面,手册介绍了...
6. **UI设计**:使用XML布局文件创建用户界面,考虑用户体验和设计原则。 7. **事件监听与处理**:如点击事件、输入事件的响应,实现用户交互功能。 8. **版本控制**:可能使用Git进行源码版本控制,学习如何提交、...
11. **Android UI设计**:Android提供了多种布局管理器(如LinearLayout、RelativeLayout、ConstraintLayout等)和视图组件,用于创建用户界面。Material Design是Google推荐的设计指南,它提供了统一的视觉风格和...
这些API涵盖了四大组件(Activity、Service、BroadcastReceiver、ContentProvider)、用户界面(UI)设计、网络通信、多媒体支持、数据库管理、设备硬件访问等众多方面。 在“Android中文翻译组——Android中文合集...
2. **UI组件**: 包括Activity、Fragment、Intent、View等,它们构成了Android应用程序的用户界面。Activity是应用程序的基本单元,负责处理用户交互;Fragment可以看作是可重用的Activity部分,适用于多屏和配置变化...
- 用户界面设计:使用XML布局文件创建用户界面,理解Material Design原则以提供良好的用户体验。 - 数据管理:了解SQLite数据库用于本地数据存储,或者使用SharedPreferences进行轻量级数据保存。 3. **数独游戏...
开发者可能使用Activity和Fragment来管理用户界面,同时运用Intent进行组件间的通信。 2. **用户界面设计** 应用界面通常包含搜索框、结果列表、单词详情页等元素。布局文件多采用XML编写,结合Java或Kotlin代码...
它与Fragment搭配使用,允许用户左右滑动来浏览不同的Fragment实例,从而创建类似翻页的效果。在"TabDemo-master"中,ViewPager作为核心组件,使得每个Tab下的内容都可以是一个独立的页面。 1. 使用ViewPager的优势...
10. **通知与消息推送**:介绍如何使用Notification API创建用户通知,以及如何集成第三方消息推送服务如Firebase Cloud Messaging(FCM)。 11. **多线程和异步任务**:讨论Android中的线程模型,包括主线程(UI...
Activity是用户界面的入口,负责与用户交互;Service则在后台运行,不与用户界面直接交互;BroadcastReceiver用于监听系统或自定义广播事件;ContentProvider则用于管理应用程序间的数据共享。 2. **Intent**:...
开发者可以通过学习这份指南,掌握如何创建一个简单的Hello World应用,如何处理设备屏幕的不同尺寸和密度,以及如何使用Fragment实现界面的动态加载。 在Android开发中,理解四大组件(Activity、Service、...
`TabLayout`、`ListView`、`Gallery`等组件是构建用户界面的常用工具,而实现它们的手势滑动功能可以极大地提升应用的交互性。本篇文章将深入探讨如何在`TabLayout`中嵌套`ListView`,并结合`Gallery`实现手势滑动,...
所有这些功能的实现都离不开用户界面的设计和事件处理。使用Android Studio中的XML布局文件创建界面元素,如EditText(文本输入框)、ListView(列表视图)、Button(按钮)等。然后,在对应的Activity或Fragment中...
3. UI设计:创建用户友好的界面,包括按钮和其他控件,让用户可以轻松地切换翻译方向。 4. 文件I/O:读取和解析外部数据库文件,将其加载到应用程序中。 5. 翻译算法:可能使用了简单的词汇对照表,也可能涉及到更...
14. **Fragment**:在大型屏幕上创建可重用的UI部件。 15. **Parcelable**和**Serializable**:用于对象序列化,常用于数据传输或保存状态。 掌握这些核心知识点,结合详细的API文档和教程,开发者就能有效利用...
在Android平台上实现滑动引导页,开发者可以使用多种技术来创建这种用户交互体验。以下将详细介绍滑动引导页的设计理念、实现方式以及相关的Android开发知识点。 1. 设计原则: - 吸引注意力:滑动引导页应具有...
10. **Android的UI设计模式**: 例如Material Design,这是谷歌推荐的设计规范,有助于创建现代、一致的用户界面。 以上只是Android API中的一部分核心概念,实际的学习过程中还需要结合具体的编程实践,不断探索和...