Android学习之Fragment

Fragment

什么是Fragment

Fragment的设计是为了解决不同分辨率的终端适配问题,下面这个图是从官方文档截取过来的,体现了这一设计思想。
在这里插入图片描述

Fragment和Activity的对比

  1. Fragment是Android3.0以后才出现的;
  2. 一个Activity可以运行多个Fragment;
  3. Fragment不能脱离Activity而存在;
  4. Activity是屏幕的主体,而Fragment是Activity的一个组成元素;

Fragment的创建

静态创建

这里要注意的是在主布局文件中声明的fragment必须要加上id,否则会出现问题。第二fragment导入的包是android.app.Fragment,千万不要导入androidx.fragment.app.Fragment。

静态创建其实指的就是使用xml文件来创建fragment,然后通过创建类继承Fragment加载自己创建的fragment的布局文件,最终就可以在主界面上显示fragmetn了。
主布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity"
    android:orientation="horizontal">

    <fragment
        android:id="@+id/fragment1"
        android:name="com.example.fragmentdemo.MyFirstFragment"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <fragment
        android:id="@+id/fragment2"
        android:name="com.example.fragmentdemo.MySecondeFragmment"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"/>

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {

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


}

fragment1布局文件

<?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">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="this is first fragment"/>

</LinearLayout>

MyFirstFragment


public class MyFirstFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, null);
        return view;
    }
}

fragment2布局文件

<?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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="this is second fragment"/>

</LinearLayout>

MySecondFragment


public class MySecondeFragmment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment2, null);
        return view;
    }
}

动态创建

fragment的动态创建指的是在加载的时候动态地把fragment挂载到指定的ViewGroup上。

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity2">


    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="这是一个TextView"
        android:textSize="30sp"/>

    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv"
        android:orientation="vertical"></LinearLayout>

</RelativeLayout>

MainActivity2
在创建的时候首先会通过 getWindowManager().getDefaultDisplay()获取屏幕的宽度和高度,从而判断是横屏还是竖屏,如果是横屏就显示MyFirstFragment,如果是竖屏就显示MySecondeFragmment。

public class MainActivity2 extends AppCompatActivity {

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


        int width = getWindowManager().getDefaultDisplay().getWidth();
        int height = getWindowManager().getDefaultDisplay().getHeight();

        FragmentManager fragmentManager = getFragmentManager();

        FragmentTransaction transaction = fragmentManager.beginTransaction();

        if (width > height) {
            //横屏
            //把fragment对象替换到viewgroup节点下
            //第一个参数:用来放置fragment的viewgroup的id
            //第二个参数:要显示的fragment对象
            //这里也可以使用add()方法达到同样的效果,remove()方法则会移除这个fragment
            transaction.replace(R.id.ll, new MyFirstFragment());
        } else {
            //竖屏
            transaction.replace(R.id.ll, new MySecondeFragmment());
        }

        transaction.commit();
    }
}

fragment添加点击事件的写法

fragment的生命周期

onAttach():建立Fragment和Activity之间的联系;
onCreateView必须重写,通过这个方法加载界面,进行初始化操作;
onDestory,如果gragment占用了某些资源,在onDestory方法中要释放资源;
onStop/onPause可以进行数据保存的操作;

fragment之间的通信

直接使用new fragment()创建的fragment对象是不会走onCreateView方法的。我们需要使用getActivity().getFragmentManager()来得到FragmentManager对象,然后通过对象的findFragmentByTag()方法去获取指定tag的Fragment对象。

MainActivity4.java

public class MainActivity4 extends AppCompatActivity {

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

        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();

        transaction.replace(R.id.ll1,new MyFirstFragment(),"first");
        transaction.replace(R.id.ll2,new MySecondeFragmment(),"second");

        transaction.commit();

    }
}

fragment2.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">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="this is second fragment"/>

</LinearLayout>

fragment1.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/btn_change"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="40sp"
        android:text="点击修改文字"/>
</LinearLayout>

MyFirstFragment.java
这里要注意的是不能直接使用findViewById()而要使用view.findViewById(),因为这个控件是在view这个视图里面的。


public class MyFirstFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment1, null);


        Button button = view.findViewById(R.id.btn_change);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager fragmentManager = getActivity().getFragmentManager();
                MySecondeFragmment secondeFragmment = (MySecondeFragmment)fragmentManager.findFragmentByTag("second");
                secondeFragmment.changeText("hahahah");
            }
        });

        return view;
    }
}

MySecondeFragmment.java


public class MySecondeFragmment extends Fragment {

    private TextView textView;

    View view;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.fragment2, null);
        return view;
    }

    public void changeText(String str) {

        textView = view.findViewById(R.id.tv);
        textView.setText(str);
    }
}

Fragment和Activity之间的传值

Activity向Fragment传值,这个时候需要在Fragment中提供一个静态的构造方法,然后利用setArguments()方法进行传值。
ListFragment 类

public class ListFragment extends Fragment {

    private static final String TAG = "ListFragment";

    public static final String TITLE = "title";
    
    private String mTitle;

    public static ListFragment newInstance(String title) {
        ListFragment fragment = new ListFragment();
        Bundle bundle = new Bundle();
        bundle.putString(TITLE,title);
        //设置参数
        fragment.setArguments(bundle);
        return fragment;
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }


    /**
     * 创建视图
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_test, container, false);

        TextView textView = view.findViewById(R.id.textView);
		//将获取到的参数设置为TextView控件的text属性的值
        textView.setText(mTitle);

        return view;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		//获取在newInstance()方法中设置的参数
        if (getArguments() != null) {
            mTitle = getArguments().getString(TITLE);
        }
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }


    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
   
}

fragment_test.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="this is a fragment"
        android:textSize="20sp"/>

</RelativeLayout>

StaticLoadFragmentActivity类

public class StaticLoadFragmentActivity extends AppCompatActivity {

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


        //动态创建Fragment

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.ll,  ListFragment.newInstance("dafawawafaf"));
        transaction.commit();



        ListFragment listFragment = ListFragment.newInstance("wterhehe");
        getFragmentManager().beginTransaction().
                add(R.id.ll1,listFragment).
                commit();
    }

}

activity_static_load_fragment.xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".StaticLoadFragmentActivity"
    android:orientation="vertical">

    <TextView
        android:text="StaticLoadFragmentActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


    <fragment
        android:id="@+id/listFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:name="com.example.fragment.ListFragment"/>


    <LinearLayout
        android:id="@+id/ll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000000"/>

    <LinearLayout
        android:id="@+id/ll1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

    </LinearLayout>

</LinearLayout>

Fragment向Acticity传值,这个时候需要在Fragment中创建接口,然后通过回调方法完成传值操作。
在ListFragment类中添加以下代码

//设置接口的方法
    public void setOnTitleClickListener(OnTitleClickListener ClickListener) {
        onTitleClickListener = ClickListener;
    }


    //定义变量
    private OnTitleClickListener onTitleClickListener;


    //定义接口
    public interface OnTitleClickListener {
        void onClick(String title);
    }

同时修改onCreateView()方法,其实就是增加了给TextView设置点击事件监听的代码,设置监听的时候判断onTitleClickListener 是否为null,不为null就给TextView设置点击事件监听回调方法。

/**
     * 创建视图
     * @param inflater
     * @param container
     * @param savedInstanceState
     * @return
     */
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_test, container, false);

        TextView textView = view.findViewById(R.id.textView);

        textView.setText(mTitle);

        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onTitleClickListener != null) {
                    onTitleClickListener.onClick(mTitle);
                }
            }
        });

        return view;
    }

修改StaticLoadFragmentActivity类


public class StaticLoadFragmentActivity extends AppCompatActivity implements ListFragment.OnTitleClickListener{

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


        //动态创建Fragment

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.ll,  ListFragment.newInstance("dafawawafaf"));
        transaction.commit();



        ListFragment listFragment = ListFragment.newInstance("wterhehe");
        getFragmentManager().beginTransaction().
                add(R.id.ll1,listFragment).
                commit();

        listFragment.setOnTitleClickListener(StaticLoadFragmentActivity.this);
    }

    @Override
    public void onClick(String title) {
        setTitle(title);
    }

}

Fragment和Fragment之间的传值和Fragment向Activity传值的方法是一样的,都是通过设置回调方法来实现。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值