AndroidTraining学习------Building a Dynamic UI with Fragments

Create a Fragment Class

  • 如何创建一个Fragment
  • 继承Fragment类并覆盖关键的生命周期方法,和操作activity差不多。
  • 唯一的不同就是你需要在Fragment中使用onCreateView()方法去加载布局。
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);    
   }
}

Add a Fragment to an Activity using XML

  • 这里是一个将两个fragment添加到一个activity的例子


    

    


  • 将布局添加到你的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);
    }
}

Note:

  • 如果你使用的是v7 appcompat library,你的activity需要继承APPCompatActivity,它是FragmentActivity的一个子类。
  • 当你的使用在layout XML File中定义Fragment这一方式添加fragment时,你不能在运行时移除fragment。如何你想在用户交互的时候替换fragment,你必须在activity第一次启动时添加fragment。

Buildinga Flexible UI

我们需要在的布局中使用重复的fragment,可根据屏幕尺寸的不同进行适配。比如在手机上可能只能显示一个fragment,而在平板电脑上需要并排显示两个fragment。
利用FragmentManager类提供的方法,你就可以在运行时添加、删除和替换Activity中的Fragment,为用户提供一种动态的体验。

Fragment added at runtime to Activity

  • 如果你想添加或移除Fragment和其他事物,你必须使用FragmentManager创建一个FragmentTransaction,这是一个可以添加、删除和替换Fragment和其他事物的Fragemnt API。
  • 在处理Fragment(特别是在运行时添加Fragment)时,请谨记以下重要规则:必须在布局中为 Fragment 提供 View 容器,以便保存 Fragment 的布局。
  • 要用一个Fragment替换另一个Fragment,Activity的布局中需要包含一个作为Fragment容器的空FrameLayout。
    
  • 在Activity内部,使用Support Library API调用getSupportFragmentManager()以获取FragmentManager,然后调用beginTransaction()创建FragmentTransaction,同时调用add()添加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);

            // 确认 Activity 使用的布局版本包含
            // fragment_container FrameLayout
            if (findViewById(R.id.fragment_container) != null) {

                // 不过,如果我们要从先前的状态还原,
                // 则无需执行任何操作而应返回
                // 否则就会得到重叠的 Fragment 。
                if (savedInstanceState != null) {
                    return;
                }

                // 创建一个要放入 Activity 布局中的新 Fragment
                HeadlinesFragment firstFragment = new HeadlinesFragment();

                // 如果此 Activity 是通过 Intent 发出的特殊指令来启动的,
                // 请将该 Intent 的 extras 以参数形式传递给该 Fragment
                firstFragment.setArguments(getIntent().getExtras());

                // 将该 Fragment 添加到“fragment_container”FrameLayout 中
                getSupportFragmentManager().beginTransaction()
                        .add(R.id.fragment_container, firstFragment).commit();
            }
        }
    }

用一个 Fragment 替换另一个 Fragment

  • 替换Fragment的步骤和添加Fragment的步骤差不多,只不过add()换成replace()
  • 当你执行替换或移除 Fragment 等 Fragment 事务时,最好能让用户向后导航和“撤消”所做更改。要通过 Fragment 事务允许用户向后导航,你必须调用 addToBackStack(),然后再执行 FragmentTransaction。
  • 当你移除或替换 Fragment 并向返回堆栈添加事务时,已移除的 Fragment 会停止(而不是销毁)。如果用户向后导航,还原该 Fragment,它会重新启动。如果你没有向返回堆栈添加事务,那么该 Fragment 在移除或替换时就会被销毁。
    // 创建 Fragment 并为其添加一个参数,用来指定应显示的文章
    ArticleFragment newFragment = new ArticleFragment();
    Bundle args = new Bundle();
    args.putInt(ArticleFragment.ARG_POSITION, position);
    newFragment.setArguments(args);

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

    // 将 fragment_container View 中的内容替换为此 Fragment ,
    // 然后将该事务添加到返回堆栈,以便用户可以向后导航
    transaction.replace(R.id.fragment_container, newFragment);
    transaction.addToBackStack(null);

    // 执行事务
    transaction.commit();

Communication with Other Fragment

  • Fragment无法直接与Fragment通信,但是可以通过Activity进行通信。

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通过调用onArticleSelected()方法(或者interface中其他的方法)就可以传递messages给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);
    }

Implement the Interface

为了接收到来自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
    }
}

Deliver a Message to a Fragment

activity可以通过findFragmentById获取Fragment实例,然后直接调用fragment的public方法。
举个例子,假如上述的例子中的activity包含另一个fragment用于显示item指定的回调方法中返回的数据。这样,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();
        }
    }
}

你可能感兴趣的:(AndroidTraining学习------Building a Dynamic UI with Fragments)