当前位置: 代码迷 >> Android >> Android培训-创建灵活的UI
  详细解决方案

Android培训-创建灵活的UI

热度:36   发布时间:2016-05-01 11:56:15.0
Android培训---创建灵活的UI

本文译自:http://developer.android.com/training/basics/fragments/fragment-ui.html

当要把应用程序设计成支持大多数屏幕尺寸的时候,你可以在不同的布局配置中复用你的Fragment,并基于可用的屏幕空间来优化用户体验。

例如,在手持设备上,它可能每次只适合显示一个Fragment作为用户界面。相反,在平板电脑上,你可能想要一组Fragment彼此相连,把更多的信息显示给用户。

图1.在不同屏幕尺寸上的同一个Activity中使用不同的配置来显示两个Fragment。在大屏幕上,两个Fragment彼此相连同时显示,但是在手持设备上,每次只会显示一个Fragment,因此在用户浏览时,两个Fragment必须交替的来显示。

为了创建动态的体验,FragmentManager类提供了在运行时添加、删除、替换Fragment的方法。

在运行是把一个Fragment添加给Activity

相比在布局文件中给Activity定义Fragment而言,你可以在Activity运行期间把Fragment添加给Activity。如果你打算在Activity生存期间来改变Fragment,这样做是必须。

要执行诸如添加或删除Fragment这样的事务处理,你必须使用FragmentManager来创建一个FragmentTransaction,它提供了添加、删除、替换以及其他Fragment事务处理的API。

如果你的Activity允许删除和替换Fragment,你应该在Activity的onCreate()方法执行期间把初始的Fragment添加给Activity。

处理Fragment时的一个重要规则---尤其是在运行时添加的那些Fragment---它们必须要有一个View布局容器,这个布局容器将会包含该Fragment的布局。

下面的布局是上节课所示布局的一个替代方案,它每次只显示一个Fragment。为了让一个Fragment替换另一个Fragment,Activity的布局包含了一个作为Fragment容器的空的FrameLayout

注意,文件名与上节课中布局文件名相同,但布局目录中没有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内部,调用getSupportFragmentManager()方法来获得支持类库API所使用的FragmentManager对象。然后调用beginTransaction()方法来创建FragmentTransaction,并调用add()方法来添加一个Fragment。

对于一个Activity,你可以使用相同的FragmentTransaction来执行多个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是在运行时被添加到FragmentLayout容器中,而不是在Activity的布局中用<fragment>元素来定义的,所以该Activity可以删除该Fragment,并用另一个Fragment来替换它。

用另一个Fragment来替换

替换Fragment的过程与添加过程类似,但是它需要使用replace()方法而不是add()方法。

要记住,在执行Fragment事务时,如替换或删除,要适当的允许用户返回和取消改变。要允许用户返回Fragment事务,在你提交FragmentTransaction之前,你必须调用addToBackStack()方法。

注意:当你删除或替换一个Fragment,并把该事务添加到回退堆栈时,被删除的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操作,否则不需要指定这个唯一名称。

  相关解决方案