美文网首页Android ViewAndroid开发经验谈Android开发
说说如何使用 Android 的碎片(Fragment)

说说如何使用 Android 的碎片(Fragment)

作者: deniro | 来源:发表于2018-02-22 17:46 被阅读80次

    开发环境:Android 2.x

    1 创建平板模拟器

    在项目中点击 “shift + F9”,这时会弹出模拟器选择框,点击 Create New Virtual Device:

    模拟器选择框

    选择 Tablet,尽量选大屏的模拟器哟,因为这样看的清楚:


    选择平板

    一路 next,最后点击运行我们刚创建的平板模拟器:

    平板模拟器

    2 基本用法

    我们在一个活动当中添加两个碎片,并让这两个碎片平分这个活动空间。

    首先新建一个左侧碎片布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="按钮"></Button>
    </LinearLayout>
    

    这个布局非常简单,只放置了一个按钮,并让它水平居中显示。接着新建右侧碎片布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00a000"
        android:orientation="vertical">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="我是右边的碎片"
            android:textSize="25sp"
            android:textColor="#ffffff"
            />
    
    </LinearLayout>
    

    这个布局把背景色设置为深绿色,并放置了一个 TextView 用于显示一段文本。

    接着新建一个继承自 Fragment 的类。注意,这里会有两个不同包下的 Fragment 类供选择,一个是系统内置的 android.app.Fragment,一个是 support-v4 库中的 android.support.v4.app.Fragment。强烈建议使用 support-v4 库中的 Fragment,因为它可以让碎片在所有 Android 系统版本中保持功能一致哟!因为 appcomcat-v7 库会把 support-v4 库一起引入进来,所以我们不必在 gradle 中引入这个库。

    LeftFragment :

    public class LeftFragment extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return inflater.inflate(R.layout.left_fragment, container, false);
        }
    }
    

    这里仅仅是重写了 Fragment 的 onCreateView() 方法,然后在这个方法中通过 LayoutInflater 的 inflate()方法将刚刚定义的 fragment_left 布局动态加载进来而已。接着我们用同样的方法创建来 RightFragment 类:

    public class RightFragment extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return inflater.inflate(R.layout.right_fragment, container, false);
        }
    }
    

    修改主活动类的布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    
        <fragment
            android:id="@+id/left_fragment"
            android:name="net.deniro.android.fragmenttest.LeftFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            />
    
    
        <fragment
            android:id="@+id/right_fragment"
            android:name="net.deniro.android.fragmenttest.RightFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            />
    </LinearLayout>
    

    这里使用了 <fragment> 标签用于在布局中添加碎片,通过 android:name 属性来显式指明要添加的碎片类名,注意一 定要是类的全名哦O(∩_∩)O~

    碎片示例

    2 动态添加碎片

    碎片真正的强大之处在于,它可以在程序运行时动态地被添加到活动当中。根据具体情况来动态地添加碎片,就可以实现程序界面的定制功能。

    我们新建一个布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="#ffff00"
        >
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textSize="20sp"
            android:text="我是另一个右碎片"
            />
    </LinearLayout>
    

    这个碎片只是把背景色改为黄色。然后再新建一个 Fragment:

    public class AnotherRightFragment extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            return inflater.inflate(R.layout.another_right_fragment, container, false);
        }
    }
    

    在主界面中加入一个 FrameLayout:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal">
    
        <fragment
            android:id="@+id/left_fragment"
            android:name="net.deniro.android.fragmenttest.LeftFragment"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            />
    
    
       <FrameLayout
           android:id="@+id/right_layout"
           android:layout_width="0dp"
           android:layout_height="match_parent"
            android:layout_weight="1"
           ></FrameLayout>
    </LinearLayout>
    

    我们打算只放一个碎片,因为 FrameLayout 布局中的所有控件都会默认摆放在布局的左上角,所以这里很适合使用 FrameLayout 布局。

    最后修改主活动中的代码:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                   replace(new AnotherRightFragment());
                }
            });
        }
    
        private void replace(Fragment fragment) {
            FragmentManager manager=getSupportFragmentManager();
            FragmentTransaction transaction=manager.beginTransaction();
            transaction.replace(R.id.right_layout,fragment);
            transaction.commit();
    
        }
    }
    

    我们给左侧碎片中的按钮注册了一个点击事件,事件内部会调用 replace() 方法动态添加碎片。动态添加碎片分为 5 步:

    1. 创建待添加的碎片实例。
    2. 获取 FragmentManager,在活动中可以直接调用 getSupportFragmentManager()方法获取。
    3. 开启一个事务。
    4. 向容器内添加或替换碎片,一般使用 replace() 方法实现,需要传入容器的 id 和待添加或替换的碎片实例。
    5. 提交事务。
    动态添加碎片

    3 在碎片中模拟栈

    上面,我们实现了向活动中动态添加碎片的功能,但通过点击按钮添加了一个碎片之后,按下 Back 键程序就会直接退出。如何才能够模拟 “返回栈” 的效果,让这个示例点击两次 Back 键才会退出程序呢?

    FragmentTransaction 中有一个 addToBackStack() 方法,可以将一个事务添加到栈中,我们修改 Activity 中的代码:

    private void replace(Fragment fragment) {
        FragmentManager manager=getSupportFragmentManager();
        FragmentTransaction transaction=manager.beginTransaction();
        transaction.replace(R.id.right_layout,fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
    

    4 碎片和活动之间的通信

    为了方便碎片和活动之间进行通信,FragmentManager 提供了一个类似于 findViewById() 的方法,专用于从布局文件中获取碎片的实例:

    //从布局文件中获取碎片实例
    RightFragment rightFragment = (RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_layout);
    

    ** 注意:要使用 getSupportFragmentManager() 来获取碎片管理器哦**

    从碎片中也可以直接返回相关的活动:

    //从碎片中调用活动
    Activity activity = rightFragment.getActivity();
    

    另外,如果需要在碎片中获取 Context 对象时,也可以直接调用 getActivity(),因为 Activity 本身就是 Context 对象啦O(∩_∩)O哈哈~

    从活动中也可以再调用碎片实例:

     //从活动中再调用碎片实例
          +  ((AppCompatActivity) activity).getSupportFragmentManager().findFragmentById(R.id.right_layout);
    

    这里记得向下转型为 AppCompatActivity 哦。

    有了上面的方法,我们就能让碎片与碎片之间通信啦:

    1. 从 A 碎片中得到相关联的活动。
    2. 通过这个活动获取 B 碎片的实例。

    A 碎片 → 关联活动 → B 碎片

    是不是很清楚呀O(∩_∩)O~

    相关文章

      网友评论

        本文标题:说说如何使用 Android 的碎片(Fragment)

        本文链接:https://www.haomeiwen.com/subject/iycztftx.html