`

使用Fragment创建动态用户界面(翻译)

 
阅读更多

使用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用户界面。

设置你的工程使用支持库

设置你的工程:

  1. 使用SDK Manager下载Android支持库
  2. 在你的Android工程的顶级层次创建一个libs目录
  3. 定位你想使用的库的jar文件,并将它拷贝到libs目录。举个例子,支持API level 4及以上版本的支持库是<sdk>/extras/android/support/v4/android-support-v4.jar
  4. 更新你的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();
         }
     }
 
}

 

  • 大小: 74.9 KB
  • 大小: 35.3 KB
分享到:
评论

相关推荐

    Android Fragment的使用方法(翻译)

    Android Fragment是Android应用程序开发中的一个重要组件,它允许开发者在单个Activity中构建模块化的界面,增强了...通过熟练掌握Fragment的使用,你可以创建更加灵活、可复用的代码结构,提升应用程序的用户体验。

    Android原生网站fragment的中文翻译

    Fragment是一种基本组件,代表Activity中的一个行为或用户界面的一部分。您可以将多个Fragment组合到一个Activity中,建立一个多窗格UI,并重用一个Fragment在多个Activity中。 Fragment可以被认为是一个模块化的...

    安卓翻译软件

    - **Activity与Fragment**:Activity代表应用的用户界面,Fragment是可嵌入到Activity中的可重用UI组件,它们共同构成了应用的视图层次。 2. **百度翻译API**: - **接入流程**:开发者需要在百度AI开放平台注册...

    Android开发者中文手册

    Fragment是Android用来构建动态用户界面的一个组件,它可以让你在一个Activity中添加、移除或替换UI部分而不需要重新启动Activity。这对于适应不同屏幕尺寸和设备形态的开发尤为重要。 在数据保存方面,手册介绍了...

    Android应用源码在线英语翻译发音项目.zip

    6. **UI设计**:使用XML布局文件创建用户界面,考虑用户体验和设计原则。 7. **事件监听与处理**:如点击事件、输入事件的响应,实现用户交互功能。 8. **版本控制**:可能使用Git进行源码版本控制,学习如何提交、...

    Android中文翻译组——Android中文合集(6)

    11. **Android UI设计**:Android提供了多种布局管理器(如LinearLayout、RelativeLayout、ConstraintLayout等)和视图组件,用于创建用户界面。Material Design是Google推荐的设计指南,它提供了统一的视觉风格和...

    Android中文翻译组—Android中文合集(7)

    这些API涵盖了四大组件(Activity、Service、BroadcastReceiver、ContentProvider)、用户界面(UI)设计、网络通信、多媒体支持、数据库管理、设备硬件访问等众多方面。 在“Android中文翻译组——Android中文合集...

    Android中文翻译组_Android中文API合集(4).zip_android_android 翻译_android开发

    2. **UI组件**: 包括Activity、Fragment、Intent、View等,它们构成了Android应用程序的用户界面。Activity是应用程序的基本单元,负责处理用户交互;Fragment可以看作是可重用的Activity部分,适用于多屏和配置变化...

    精品专题资料(2021-2022年收藏)基于android数独游戏设计翻译译文.doc

    - 用户界面设计:使用XML布局文件创建用户界面,理解Material Design原则以提供良好的用户体验。 - 数据管理:了解SQLite数据库用于本地数据存储,或者使用SharedPreferences进行轻量级数据保存。 3. **数独游戏...

    Android代码-支持多种查词模式的安卓英语词典

    开发者可能使用Activity和Fragment来管理用户界面,同时运用Intent进行组件间的通信。 2. **用户界面设计** 应用界面通常包含搜索框、结果列表、单词详情页等元素。布局文件多采用XML编写,结合Java或Kotlin代码...

    TabDemo-master

    它与Fragment搭配使用,允许用户左右滑动来浏览不同的Fragment实例,从而创建类似翻页的效果。在"TabDemo-master"中,ViewPager作为核心组件,使得每个Tab下的内容都可以是一个独立的页面。 1. 使用ViewPager的优势...

    《宅男的android开发指南》(翻译)--10完整版

    10. **通知与消息推送**:介绍如何使用Notification API创建用户通知,以及如何集成第三方消息推送服务如Firebase Cloud Messaging(FCM)。 11. **多线程和异步任务**:讨论Android中的线程模型,包括主线程(UI...

    Android中文翻译组——Android中文API合集(3).zip_android_手册

    Activity是用户界面的入口,负责与用户交互;Service则在后台运行,不与用户界面直接交互;BroadcastReceiver用于监听系统或自定义广播事件;ContentProvider则用于管理应用程序间的数据共享。 2. **Intent**:...

    android开发指南

    开发者可以通过学习这份指南,掌握如何创建一个简单的Hello World应用,如何处理设备屏幕的不同尺寸和密度,以及如何使用Fragment实现界面的动态加载。 在Android开发中,理解四大组件(Activity、Service、...

    Tablayou嵌套ListView以及gallery实现手势滑动 支持多语言

    `TabLayout`、`ListView`、`Gallery`等组件是构建用户界面的常用工具,而实现它们的手势滑动功能可以极大地提升应用的交互性。本篇文章将深入探讨如何在`TabLayout`中嵌套`ListView`,并结合`Gallery`实现手势滑动,...

    Android实现记事本,简易词典,自动登陆,电话本功能.zip

    所有这些功能的实现都离不开用户界面的设计和事件处理。使用Android Studio中的XML布局文件创建界面元素,如EditText(文本输入框)、ListView(列表视图)、Button(按钮)等。然后,在对应的Activity或Fragment中...

    一个简单的英汉词典,点击按钮切换汉译英

    3. UI设计:创建用户友好的界面,包括按钮和其他控件,让用户可以轻松地切换翻译方向。 4. 文件I/O:读取和解析外部数据库文件,将其加载到应用程序中。 5. 翻译算法:可能使用了简单的词汇对照表,也可能涉及到更...

    android应用开发API

    14. **Fragment**:在大型屏幕上创建可重用的UI部件。 15. **Parcelable**和**Serializable**:用于对象序列化,常用于数据传输或保存状态。 掌握这些核心知识点,结合详细的API文档和教程,开发者就能有效利用...

    滑动引导页

    在Android平台上实现滑动引导页,开发者可以使用多种技术来创建这种用户交互体验。以下将详细介绍滑动引导页的设计理念、实现方式以及相关的Android开发知识点。 1. 设计原则: - 吸引注意力:滑动引导页应具有...

    android资料

    10. **Android的UI设计模式**: 例如Material Design,这是谷歌推荐的设计规范,有助于创建现代、一致的用户界面。 以上只是Android API中的一部分核心概念,实际的学习过程中还需要结合具体的编程实践,不断探索和...

Global site tag (gtag.js) - Google Analytics