Android学习之路-基础知识-Fragement(1)

碎片是什么

碎片(Fragment)是一种可以嵌在活动当中的UI片段,它能让程序更加合理和充分地利用大屏幕空间,因而在平板上应用得非常广泛。我们在编写平板app时,为了更好的利用平板的大屏优势,会把阅读列表放在左边,而详细内容放在右边,这也是和手机只显示列表,只有点击列表会进入详细页面不同的地方,显示效果如图:
怎么实现这个效果呢,废话不多说,开始正题~

碎片的使用方式

初步接触碎片

新建一个FragmentTest项目,这是一个最简单的碎片实例。在一个活动中添加两个碎片,并且让这两个碎片平分活动空间。
(1)在res/layout下新建一个left_fragment.xml。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Button"
        />

</LinearLayout>

布局文件中只放了一个水平居中的按钮button。
(2)在res/layout下再新建一个right_fragment.xml文件。代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:background="#00FF00"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is right fragment"
        />

</LinearLayout>
布局文件中只有一个TextView,显示一句话“This is right fragment”,然后背景颜色是绿色。
(3)在java/com.XXX(你自己的包名).fragmenttest下新建LeftFragment类,其继承android.support.v4.app下的Fragment类(此处查看第一行代码第二版P145页 有详细介绍)。代码如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Deiatg on 2017/3/4.
 */

public class LeftFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //能动态地加载布局的函数inflate()
        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;
    }
}

这里仅仅重写了Fragment类中的onCreateView()方法,这个方法的作用就是使用LayoutInflater的inflate()类将刚才定义好的left_fragment.xml动态加载进来。用同样的方法创建一份RightFragment类,代码如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Deiatg on 2017/3/4.
 */

public class RightFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //能动态地加载布局的函数inflate()
        View view = inflater.inflate(R.layout.right_fragment, container, false);
        return view;
    }
}
代码基本相同,我们继续。
(4)修改activity_main中的代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.open_open.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

    
    <fragment
        android:id="@+id/right_fragment"
        android:name="com.open_open.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

</LinearLayout>

代码将两个碎片一左一右放入主布局中,注意的是要将fragment的完整包名放在android:name中。

之后运行程序就能得到一个含有两个碎片的app了。

动态添加碎片

在之前的代码基础上继续完善。
(1)新建another_right_fragment.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:background="#FFFF00"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is another right fragment"/>

</LinearLayout>

跟right_fragment.xml基本完全一样,只是背景颜色变成了黄色。
(2)建立AnotherRightFragment类,代码如下:
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by Deiatg on 2017/3/4.
 */

public class AnotherRightFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //能动态地加载布局的函数inflate()
        View view = inflater.inflate(R.layout.another_right_fragment, container, false);
        return view;
    }
}

代码同样很简单,在onCreateView()方法中加载刚才创建好的another_right_fragment.xml文件。这就准备好了另一个碎片,之后我们看一下如何将其动态地添加到活动中。
(3)修改activity_main.xml文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.open_open.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,为什么这么做呢?其实这样做是因为我们想要在活动里加载多个Fragment,那么就不能再主布局中将fragment写死,而是只放一个FrameLayout,然后通过在MainActivity里的相关方法对FrameLayout里的内容进行替换,这样就达到了我们的目的。于是下一个动作就是修改MainActivity。
(4)修改MainActivity,代码如下:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
        repalceFragment(new RightFragment());
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                repalceFragment(new AnotherRightFragment());
                break;
            default:
                break;
        }
    }

    private void repalceFragment (Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.commit();
    }
}
代码中MainActivity类实现了OnClickListener接口,这里可以参考我的另一篇文章:链接 。代码中首先我们给左侧碎片中的button按钮注册了一个点击事件,只有点击这个按钮就会调用我们自定义的方法repalceFragment(),这个方法能够当前布局替换一个新的碎片。点击按钮将右侧碎片换成另一个碎片。结合replaeFragment()方法的代码可以看到,动态添加碎片分为五步。
(1)创建待添加的碎片实例;
(2)获取FragmentManager, 在活动中可以 直接通过调用getSupportFragmentManager()方法得到;
(3)开启一个事务,通过调用beginTransaction()方法开启;
(4)向容器内添加或者替换碎片,一般使用replace()方法实现,需要传入容器的id和待添加的碎片实例;
(5)提交事务,调用commit()方法完成。
这样就完成了在活动中动态添加碎片的活动,重新运行程序,点击按钮就会发现屏幕右侧发生改变。

在碎片中模拟返回栈

也就是当有多个碎片都被动态添加,我们在调用了它们之后不想按返回键直接退出程序,而是逐个返回碎片,最后退出程序。想达到这种类似栈的返回操作其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以用于讲一个事务添加到返回站中,修改代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
     ……
    private void repalceFragment (Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
}
我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接收一个名字用于描述返回栈的状态,一般传入null即可。重新运行程序,我们发现,在碎片中模拟返回栈这个功能我们完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章