学习之鸿蒙&Android学习

Fragment

2021-05-28  本文已影响0人  Amy木婉清

1.什么是Fragment

Fragment的两个特性

1)具备生命周期
2)必须委托在activity中才能运行

2.Fragment使用方法

创建一个Activity:

public class MainActivity extends AppCompatActivity {

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

创建一个fragment

public class BlankFragment1 extends Fragment {
    private View root;
    private TextView textView;
    private Button button;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (root == null) {
            root = inflater.inflate(R.layout.fragment_blank1, container, false);
        }
        textView = root.findViewById(R.id.textview);
        button = root.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.setText("Yes,I am ,and you?");
            }
        });
        return root;
    }
}

fragment布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".BlankFragment1">

    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="@string/hello_blank_fragment" />
    <Button
        android:text="how are you?"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:id="@+id/button"/>

</LinearLayout>

activtiy布局

<?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"
    android:orientation="vertical"
    tools:context=".MainActivity">
<fragment
    android:id="@+id/fragment1"//id必须有
    android:name="com.example.fragmenttest.BlankFragment1"//name必须有
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />
</LinearLayout>

运行结果,点击按钮,内容变成Yes......

在activity中添加两个fragment

复制fragment1,命名fragment2

public class BlankFragment2 extends Fragment {
    private View root;
    private TextView textView;
    private Button button;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (root == null) {
            root = inflater.inflate(R.layout.fragment_blank1, container, false);
        }
        textView = root.findViewById(R.id.textview);
        button = root.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.setText("Yes,I am ,and you?");
            }
        });
        return root;
    }
}

activtiy布局新增fragment

<?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"
    android:orientation="vertical"
    tools:context=".MainActivity">
<fragment
    android:id="@+id/fragment1"
    android:name="com.example.fragmenttest.BlankFragment1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="1"
    />
    <fragment
        android:id="@+id/fragment2"
        android:name="com.example.fragmenttest.BlankFragment2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        />
</LinearLayout>

点击按钮后的运行结果:


image.png
Fragment的动态添加与管理

创建Activity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


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

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn1:
                replaceFragment(new BlankFragment());
                break;
            case R.id.btn2:
                replaceFragment(new ItemFragment());
        }
    }

    //动态切换fragment
    private void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager  = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.framelayout,fragment);
        transaction.commit();
    }
}

创建布局

<?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"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn1"
        android:text="change"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/btn2"
        android:text="replace"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <FrameLayout
        android:id="@+id/framelayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"/>

</LinearLayout>

创建一个BlankFragment 一个listFragment


image.png

运行结果:
点击按钮一change


image.png

点击按钮二replace


image.png
Activity与Fragment之间的通信

原生方案:bundle
在studio中输入logt,就会直接声明出来log中的TAG变量,即:

 private static final String TAG = "BlankFragment";

1.从Activtiy发送信息到Fragment
首先在MainActivtiy中的点击事件中添加Bundle

    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1:
                Bundle bundle = new Bundle();
                bundle.putString("message", "work hard no why");
                BlankFragment blankFragment = new BlankFragment();
                blankFragment.setArguments(bundle);
                replaceFragment(blankFragment);
                break;
        }
    }

其次在Fragment的onCreate中获取

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        String string = bundle.getString("message");
        Log.d(TAG, "onCreate: "+string);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

点击第一个按钮后,运行结果就会把刚刚传入的信息打印出来,即work hard no why.

动态添加fragment步骤:

1) 创建一个待处理的fragment
2)获取FragmentManager,一般都是通过getSupportFragmentManager();
3)开启一个事物transaction,一般调用fragmentManager的beginTransaction
4)使用transaction进行fragmenet的替换
5)提交事务 transaction.commit();

fragment与Activity通信的接口方案

Java语言中类与类之间通信的方案:

1.接口回调

首先创建一个接口:

package com.example.fragmanager;

/**
 * @author zwp
 * @description:
 * @date: 2021/5/26 14:28
 */
public interface IFragmentCallBack {
    void sendMsgToActivity(String msg);
    String getMsgFromActivity(String msg);
}

在fragment中创建一个实现接口的类:

package com.example.fragmanager;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class BlankFragment extends Fragment {
    private static final String TAG = "BlankFragment";
    private View rootView;

    public BlankFragment() {

    }

    private IFragmentCallBack iFragmentCallBack;

    public void setIFragmentCallBack(IFragmentCallBack callBack) {
        iFragmentCallBack = callBack;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        String string = bundle.getString("message");
        Log.d(TAG, "onCreate: " + string);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = inflater.inflate(R.layout.fragment_blank, container, false);
        }
        Button btn = rootView.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                iFragmentCallBack.sendMsgToActivity("hello,I am from fragment");//发送消息给activity
            }
        });
        return rootView;
    }

    @Override
    public void onResume() {
        super.onResume();

    }
}

Fragment的xml

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

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/hello_blank_fragment" />

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="数据传递" />
</FrameLayout>

在Activtiy中引用

  @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1:
                Bundle bundle = new Bundle();
                bundle.putString("message", "work hard no why");
                BlankFragment blankFragment = new BlankFragment();
                blankFragment.setArguments(bundle);
                //匿名內部类
                blankFragment.setIFragmentCallBack(new IFragmentCallBack() {
                    @Override
                    public void sendMsgToActivity(String msg) {
                        Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public String getMsgFromActivity(String msg) {
                        return null;
                    }
                });
                replaceFragment(blankFragment);
                break;
        }
    }

效果如下图所示,点击数据传递按钮:


image.png
从Activtiy中取消息

Fragment

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = inflater.inflate(R.layout.fragment_blank, container, false);
        }
        Button btn = rootView.findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // iFragmentCallBack.sendMsgToActivity("hello,I am from fragment");//发送消息给activity
                String msg = iFragmentCallBack.getMsgFromActivity("从Activity取消息");
                Toast.makeText(BlankFragment.this.getContext(), msg, Toast.LENGTH_SHORT).show();
            }
        });
        return rootView;
    }

Activity

  @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn1:
                Bundle bundle = new Bundle();
                bundle.putString("message", "work hard no why");
                BlankFragment blankFragment = new BlankFragment();
                blankFragment.setArguments(bundle);
                //匿名內部类
                blankFragment.setIFragmentCallBack(new IFragmentCallBack() {
                    @Override
                    public void sendMsgToActivity(String msg) {
                        Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public String getMsgFromActivity(String msg) {
                        return "Hello,I am from Activity";
                    }
                });
                replaceFragment(blankFragment);
                break;
            case R.id.btn2:
                replaceFragment(new ItemFragment());
        }
    }

运行结果:


image.png
通信的其他方案----->Eventbus LiveData
Fragment的生命周期
image.png
onAttach、onDetach:Fragment与Activtiy之间的绑定和解绑
因为Fragment依托于Activity,所以二者要进行绑定,使用结束之后要解绑。
常遇见的问题:在Fragment中获取Activtiy内容,获取到变量为空的时候,根本原因就是没有把相应生命周期执行放在onAttach、onDetach之间执行。

onCreate:fragment的创建------对Activtiy传过来的bundle进行解析
onDestroy:fragment的销毁
onCreateView:对UI的创建 Inflater.inflate......
onActivtiyCreated:Activtiy已经创建了
下面的几个生命周期与Activity相对应。

Fragment生命周期

1.打开页面
onCreate()-->onCreateView()-->onActivityCreated()-->onStart()-->onResume()
2.按下主屏键
onpause()-->onStop()
3.重新打开页面
onStart()-->onResume()
4.按后退键
onPause()-->onStop()-->onDestroyView()-->onDestroy()-->onDetach()

Fragment生命周期注意事项

1.将来开发者会围绕fragment生命周期花很多时间来解决问题
2.Fragment的使用一定是需要在生命周期函数onAttach与onDetach之间
3.Fragment的使用一定要遵守生命周期管理的规则,在正确的地方写恰当的代码

案例:Fragment与ViewPager滑动效果
ViewPager的基本应用

ViewPager2依赖:

    dependencies {
        implementation "androidx.viewpager2:viewpager2:1.0.0"
    }

ViewPager2自带懒加载功能

ViewPager使用流程

1.定义ViewPager
2.为ViewPager构建Adapter
创建Activtiy,并在xml中引用viewPager
activity

package com.example.viewpagerandfragment;

import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewPager2 viewPager = findViewById(R.id.viewPager);
        ViewPageAdapter viewPageAdapter = new ViewPageAdapter();
        viewPager.setAdapter(viewPageAdapter);
    }
}

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=".MainActivity">
    <androidx.viewpager2.widget.ViewPager2
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/viewPager"
        android:background="@color/colorAccent"/>
</LinearLayout>

创建一个item,用于显示布局内容

<?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"
    android:id="@+id/container">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:id="@+id/tvTitle"
        android:textColor="#ff4532"
        android:textSize="32sp"
        android:text="hello"/>
</RelativeLayout>

创建adapter:

package com.example.viewpagerandfragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zwp
 * @description:
 */
public class ViewPageAdapter extends RecyclerView.Adapter<ViewPageAdapter.ViewPagerViewHolder> {
    private List<String> titles = new ArrayList<>();//每个页面显示的具体内容
    private List<Integer> colors = new ArrayList<>();//每个页面的颜色
    ViewPageAdapter(){
        titles.add("hello");
        titles.add("6");
        titles.add("7");
        titles.add("8");
        titles.add("9");
        titles.add("1");
        titles.add("2");
        titles.add("3");
        titles.add("4");
        titles.add("5");
        colors.add(R.color.white);
        colors.add(R.color.colorPrimary);
        colors.add(R.color.colorPrimaryDark);
        colors.add(R.color.black);
        colors.add(R.color.red);
        colors.add(R.color.colorAccent);
        colors.add(R.color.white);
        colors.add(R.color.red);
        colors.add(R.color.black);
        colors.add(R.color.colorPrimary);
    }
    @NonNull
    @Override
    public ViewPagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new ViewPagerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pager,parent,false));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewPagerViewHolder holder, int position) {
        holder.mTv.setText(titles.get(position));
        holder.mContainer.setBackgroundResource(colors.get(position));
    }


    @Override
    public int getItemCount() {
        return 10;
    }

    class ViewPagerViewHolder extends RecyclerView.ViewHolder{

        TextView mTv;
        RelativeLayout mContainer;
        public ViewPagerViewHolder(@NonNull View itemView) {
            super(itemView);
            mContainer = itemView.findViewById(R.id.container);
            mTv = itemView.findViewById(R.id.tvTitle);
        }
    }
}

运行结果即十个页面显示内容不一致并且可以左右切换滑动

上一篇下一篇

猜你喜欢

热点阅读