展会信息港展会大全

创建灵活的用户界面-Android Fragment
来源:互联网   发布日期:2015-09-29 10:53:23   浏览:1999次  

导读:创建灵活的用户界面-android Fragment.Android Support Library(支持库)提供了包含一个API库的JAR文件,当你的应用运行在Android早期版本时,Support Library(支持库)允许你的应用使用最近版本的Android AP......

创建灵活的用户界面-android Fragment.

Android Support Library(支持库)提供了包含一个API库的JAR文件,当你的应用运行在Android早期版本时,Support Library(支持库)允许你的应用使用最近版本的Android API。例如:Support Library提供了Fragment版本的API,这样你就可以在Android1.6(API level 4)或者更高的版本上使用Fragment API了。

这节课将为你演示如何在你的应用中设置Support Library,并且使用Fragment构建一个动态的应用UI。

设置你项目的支持库 - Set Up Your Project With the Support Library

设置你的项目:

1使用SDK Manager下载Android Support包

2在你项目的顶层目录下创建libs目录

3找到你想要引入库的JAR文件,然后将它复制到libs目录

例如:支持API Level 4的库就位于<sdk>/extras/android/support/v4/android-support-v4.jar.

译者注:这个<sdk>代表着你安装android sdk的目录,比如本人的完全目录为:E:\android-sdk-windows\extras\android\support\v4\android-support-v4.jar

4修改你的manifest文件,设置最低级别为API level 4,目标API level为最新版本:

<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" />

图1: Android SDK Manager,其中Android Support package已选中。

导入支持库API - Import the Support Library APIs

支持库包含了一系列的API,这些API或许在最近的Android版本中增加了,或许在platform(平台)中根本不存在,而仅仅当你开发特定的应用功能时提供了附加的支持。

你可以在android.support.v4.*这个平台支持库中找到所有的API参考文档。

警告:请确保你不是恰好在一个老系统版本中使用新的API,请确认你引入的Fragment类以及相关的API都来自android.support.v4.app包

import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; ...

当使用Support Library创建有关fragment的Activity时,你必须继承FragmentActivity类,而不是传统的Activity类,你将会在下一节课中学习到一些简单的关于fragment以及Activity的代码。

Creating a Fragment

你可以认为fragment是activity的模块化组件,它拥有自己的生命周期,接受它自己的输入事件,你也可以在运行activity的时候添加或 者移除它(有点像 子activity 你可以在不同的activity中重用) 这节课演示怎么样使用Support Library继承Fragment类,如此你的app(应用)就能与运行android1.6老版本的系统设备兼容 。

注意:如果你因为一些其他原因决定你的app需要的最低API版本为11或者更高,那你就没必要使用Support Library,而可以直接使用框架内置的Fragment类和相关API,要知道这节课主要关注于使用来自Support Library的API,使用特定包名下的API跟内置在平台(API)的还是略有不同的

创建Fragment类 (Create a Fragment Class)

要创建一个fragment需要继承Fragment类,然后重写关键的生命周期方法插入你自己的应用逻辑,操作的方式跟创建一个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也应该要实现其他的生命周期方法来管理它的状态,当fragment被activity添加或者删除,当 activity生命周期状态转换时(类似这种操作都会影响到fragment的状态); 例如:当activity的onPuase()方法被调用的时候,所有activity中的fragment也都会接收到onPause()方法的调用。

更多关于fragment生命周期和回调函数的方法都可以在Fragment 开发指南中找到。

使用XML添加Fragment到Activity (Add a Fragment to an Activity using XML)

fragment是可重用的,模块化的UI组件,每一个Fragment实例必须与父类FragmentActivity相关联,你可以通过在你 Activity布局XML文件中定义每一个fragment来获得关联。 注意:FragmentActivity是在系统版本低于API level 11时由Support Library提供用来管理fragment的特殊activity,如果你支持的最低系统版本是API level 11或者更高,那你可以直接使用常规的Activity。 以下是一个例子:当设备屏幕被认为 大 的时候,一个布局文件添加了两个fragment到activity 译者注:当屏幕比较大的时候(比如平板)是可以同时显示两个fragment的,但是屏幕比较小(比如普通手机)同一时间只能显示一个fragment, 这是由于它们的屏幕尺寸造成的,后续的课程也会提到这个 这个布局文件被指定在 高 分辨率的目录名下。(译者注:请注意下面xml的目录结构:是在res目录下的layout-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>

注:更多关于为不同屏幕大小创建布局,请参照Supporting Different Screen Sizes(支持不同的屏幕大小)

这里列举了在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添加进去,我们将会在下一节课中演示。

构建灵活的用户界面 (Build a flexible UI)

当你设计支持广泛屏幕大小的应用时,你可以在不同的布局配置中重用你的frament,在可用的屏幕空间基础上优化用户体验。 例如,在手持设备上,对于一个单窗口的用户界面来说同一时间可能只适合显示一个fragment。 反之,你可能想在尺寸更大平板的两端设置更多的fragment以显示更多的信息给用户

如上图:两个fragment,同一个activity,不同的配置,显示在不同的屏幕尺寸上。在大的屏幕中,两个fragment各占屏幕一端,但是在 手持设备中,在同一时间,仅仅只占有一个fragment,两个fragment必须相互替换为用户导航。为创建一个动态的体 验,FragmentManager类提供了方法允许你在activity运行时对fragment进行添加,移除,和替换。

Add a Fragment to an Activity at Runtime

相比上节课提到的使用<fragment>标签在布局文件中为activity定义一个fragment组件,更好的方式是在activity运行时添加,而且这样做是必须的,如果你想在activity的生命周期中变换fragment的话。

执行类似添加或者删除fragment的事务,你必须使用FragmentManager创建一个FragmentTransaction,它提供了添 加,删除以及其他fragment事务的API。 如果你的activity允许移除或者替换fragment,你应该在activity的onCreate()方法中添加初始化的fragment。 在你处理fragment的时候,有一个很重要的规则(尤其是你在运行时添加fragment) 那就是你的fragment放置位置的布局中必须有一个视图容器。 下面这个布局是上节课在同一时间只显示一个fragment布局的替代品,为了将一个fragment替换成另一个,这个activity布局包含了一个 空的FrameLayout作为fragment容器。 注意这个文件名跟上节课的布局文件名字一样,但是这个布局并没有指定在 高分辨率 目录中(译者注:请注意下面xml的路径,res/layout这个 layout文件夹并没有像上节课提到的是一个layout-large文件夹),如此这个布局是用在比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中,使用Support LibraryAPI,调用getSupportFragmentManager()可以得到一个FragmentManager对象,之后调用 beginTransaction去创建一个FragmentTransaction对象, 再调用add()方法即可添加一个fragment。 你可以对activity使用同一个FragmentTransaction对象去执行多个fragment事务,当你确定要做这些操作时,你必须调用 commint()方法。 例如,以下代码演示怎样添加一个fragment到前面的layout:

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替换当前(Replace One Fragment with Another)

替换一个fragment的过程跟添加差不多,但是需要的是replace()方法,而不是add()方法。 需要注意的是,当你执行fragment事务时,比如替换或者删除一个fragment。允许用户 后退 或者 撤销 改变通常是比较合适的做法。为了让 用户可以通过fragment事务 后退 ,你必须在你提交fragment事务之前调用 addToBackStack()方法。

注意:当你移除或者替换fragment时将事务添加到堆栈中,被移除的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();

addToBackStack()方法有一个可选的字符串参数,用来指定事务的唯一名称。这个名称不是必须的除非你打算使用FragmentManager.BackStackEntry API执行跟高级的fragment操作。

目录

1 与其他Fragment交互 Communication with Other Fragments

1.1 定义一个接口 Define an Interface

1.2 实现接口 Implement the Interface

1.3 Deliver a Message to a Fragment

与其他Fragment交互 Communication with Other Fragments

为了重用Fragment UI组件,你应该将Fragment建立成完全独立,模块化并且定义了自己布局和行为的组件。一旦你定义了这些可重用的Fragment, 你可以通过activity,应用程序逻辑使它们关联,交互以组成一个整体复合型UI。 通常情况下,你希望一个Fragment可以与另一个交互。比如在用户事件的基础上去修改内容,所有Fragment到Fragment的交互都是通过相 关联的activity来做的,两个fragment应该从不直接交互;

定义一个接口 Define an Interface

为了允许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了。 例如,当 用户点击list item(list子项)时就会调用下面在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); }

实现接口 Implement the Interface

为了接收来自fragment的事件回调,主activity(你需要用来与fragment交互的activity)必须实现定义在fragment类中的接口。 例如:下面这个activity就实现了上一例子中的接口:

public static class MainActivity extends Activity implements HeadlinesFragment.OnHeadlineSelectedListener{ ...

public void onArticleSelected(Uri articleUri) { // The user selected the headline of an article from the HeadlinesFragment // Do something here to display that article } }

Deliver a Message to a 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(); } } }

赞助本站

人工智能实验室

相关热词: Fragment 用户界面

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港