Android Fragment(2)

参考:

片段https://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
Fragment 使用(1)http://blog.csdn.net/u012005313/article/details/55215552


主要内容

  1. 动态添加,替换和移除 fragment
  2. 返回栈的使用
  3. activity 通信

动态添加,替换和移除 fragment

设置 3 个按钮,分别用来添加,替换和移除 fragment

MainActivity.java 如下:

public class MainActivity extends AppCompatActivity{
    private static final String TAG = "MainActivity";

    private Button btnAdd;
    private Button btnReplace;
    private Button btnRemove;

    private FrameLayout flContainer;

    private FragmentManager fragmentManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        btnAdd = (Button) findViewById(R.id.btn_add);
        btnReplace = (Button) findViewById(R.id.btn_replace);
        btnRemove = (Button) findViewById(R.id.btn_remove);
        flContainer = (FrameLayout) findViewById(R.id.fl_container);

        fragmentManager = getSupportFragmentManager();

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                addFragment();
            }
        });

        btnReplace.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                replaceFragment();
            }
        });

        btnRemove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                removeFragment();
            }
        });
    }

    private void addFragment() {
        OneFragment onefragment = new OneFragment();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        fragmentTransaction.add(R.id.fl_container, onefragment);
        fragmentTransaction.commit();

        btnAdd.setEnabled(false);
        btnReplace.setEnabled(true);
    }

    private void replaceFragment() {
        TwoFragment fragment = new TwoFragment();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        fragmentTransaction.replace(R.id.fl_container, fragment, "twoFragment");
        fragmentTransaction.commit();

        btnReplace.setEnabled(false);
        btnRemove.setEnabled(true);
    }

    private void removeFragment() {
        TwoFragment fragment = (TwoFragment)fragmentManager.findFragmentByTag("twoFragment");
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        fragmentTransaction.remove(fragment);
        fragmentTransaction.commit();

        btnRemove.setEnabled(false);
        btnAdd.setEnabled(true);
    }
}

activity_main.xml 如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zj.fragmentdemo.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/btn_add"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="ADD" />

            <Button
                android:id="@+id/btn_replace"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:enabled="false"
                android:text="REPLACE" />

            <Button
                android:id="@+id/btn_remove"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:enabled="false"
                android:text="REMOVE" />

        </LinearLayout>

        <FrameLayout
            android:id="@+id/fl_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@color/colorAccent" />

    </LinearLayout>


</android.support.design.widget.CoordinatorLayout>

activity 中进行 fragment 的添加,替换和移除,使用 FragmentTransaction

FragmentTransaction 通过 FragmentManager 获得:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

Note 1:每次进行 fragment 操作,必须重新获取 FragmentTransaction

Note 2:每次进行 fragment 更改后,必须调用 commit 方法

添加

add 方法有多种重载,介绍其中两种:

/**
 * Calls {@link #add(int, Fragment, String)} with a null tag.
 */
public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment);

/**
 * Add a fragment to the activity state.  This fragment may optionally
 * also have its view (if {@link Fragment#onCreateView Fragment.onCreateView}
 * returns non-null) into a container view of the activity.
 * 
 * @param containerViewId Optional identifier of the container this fragment is
 * to be placed in.  If 0, it will not be placed in a container.
 * @param fragment The fragment to be added.  This fragment must not already
 * be added to the activity.
 * @param tag Optional tag name for the fragment, to later retrieve the
 * fragment with {@link FragmentManager#findFragmentByTag(String)
 * FragmentManager.findFragmentByTag(String)}.
 * 
 * @return Returns the same FragmentTransaction instance.
 */
public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment,
        @Nullable String tag);

第一个参数 containerViewId 指定 activity 中放置 fragment 的位置

第二个参数 fragment 指定要添加的片段

第三个参数 tag 表示该 fragment 的标识符,之后可以通过函数 findFragmentByTag 找回该 fragment

替换

replace 函数有 2 个重载方法:

/**
 * Calls {@link #replace(int, Fragment, String)} with a null tag.
 */
public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment);

/**
 * Replace an existing fragment that was added to a container.  This is
 * essentially the same as calling {@link #remove(Fragment)} for all
 * currently added fragments that were added with the same containerViewId
 * and then {@link #add(int, Fragment, String)} with the same arguments
 * given here.
 * 
 * @param containerViewId Identifier of the container whose fragment(s) are
 * to be replaced.
 * @param fragment The new fragment to place in the container.
 * @param tag Optional tag name for the fragment, to later retrieve the
 * fragment with {@link FragmentManager#findFragmentByTag(String)
 * FragmentManager.findFragmentByTag(String)}.
 * 
 * @return Returns the same FragmentTransaction instance.
 */
public abstract FragmentTransaction replace(@IdRes int containerViewId, Fragment fragment,
        @Nullable String tag);

其参数和 add 方法一致

移除

remove 方法:

/**
 * Remove an existing fragment.  If it was added to a container, its view
 * is also removed from that container.
 * 
 * @param fragment The fragment to be removed.
 * 
 * @return Returns the same FragmentTransaction instance.
 */
public abstract FragmentTransaction remove(Fragment fragment);

需要提供要移除的 fragment 对象

实现:

这里写图片描述


返回栈的使用

由上面操作可知,进行 fragment 的操作如下

  • 获取 FragmentTransaction 对象
  • 执行 add / replace / remove 操作
  • 执行 commit 提交更改

可以将 fragment 更改记录下来,方法是在 commit 之前调用函数 addToBackStack:

/**
 * Add this transaction to the back stack.  This means that the transaction
 * will be remembered after it is committed, and will reverse its operation
 * when later popped off the stack.
 *
 * @param name An optional name for this back stack state, or null.
 */
public abstract FragmentTransaction addToBackStack(@Nullable String name);

当执行上面的操作后,点击 返回键 能够回退到上一步的 fragment

或者调用 FragmentManager.popBackStack 模拟返回键操作:

/**
 * Pop the top state off the back stack.  Returns true if there was one
 * to pop, else false.  This function is asynchronous -- it enqueues the
 * request to pop, but the action will not be performed until the application
 * returns to its event loop.
 */
public abstract void popBackStack();

修改 MainActivity.java 如下:

public class MainActivity extends AppCompatActivity {

    ...

    private void initView() {
        ...

        btnRemove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                removeFragment();
                popFragment();
            }
        });
    }

    private void addFragment() {
        ...

        fragmentTransaction.add(R.id.fl_container, onefragment);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();

        btnAdd.setEnabled(false);
        btnReplace.setEnabled(true);
        btnRemove.setEnabled(true);
    }

    private void replaceFragment() {
        ...

        fragmentTransaction.replace(R.id.fl_container, fragment, "twoFragment");
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();

        ...
    }

    private void removeFragment() {
        ...

//        btnRemove.setEnabled(false);
//        btnAdd.setEnabled(true);
    }

    private void popFragment() {
        fragmentManager.popBackStack();
    }
}

这里写图片描述

监听器

还可以设置 FragmentManager.addOnBackStackChangedListener 对返回栈操作进行监听:

/**
 * Interface to watch for changes to the back stack.
 */
public interface OnBackStackChangedListener {
    /**
     * Called whenever the contents of the back stack change.
     */
    public void onBackStackChanged();
}

修改 MainActivity.java 如下:

public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener {
    private static final String TAG = "MainActivity";

    ...s

    @Override
    public void onBackStackChanged() {
        Log.e(TAG, "onBackStackChanged: "+fragmentManager.getBackStackEntryCount());
    }

    private void initView() {
        ...

        fragmentManager = getSupportFragmentManager();
        fragmentManager.addOnBackStackChangedListener(this);

        ...
    }

    ...
}

activity 的事件回调

可以在 fragment 中创建一个回调接口,在 activity 实现该接口即可

比如,在 fragment 中创建一个点击事件:

public interface OnClickListener {
    void onFragmentClick(View var1);
}

在创建 fragment 时进行绑定:

public class OneFragment extends Fragment {
    OnClickListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnClickListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnClickListener");
        }
    }
    ...
}

activity 中实现 onFragmentClick 方法即可

Note:ClassCastException 属于运行时异常

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值