Fragment
- Fragment表示应用界面中可重复使用的一部分。Fragment 定义和管理自己的布局,具有自己的生命周期,并且可以处理自己的输入事件。Fragment 不能独立存在,而是必须由 Activity 或另一个 Fragment 托管。Fragment 的视图层次结构会成为宿主的视图层次结构的一部分,或附加到宿主的视图层次结构。
- activity_main.xml中的fragment必须有id
- 当 Activity 处于
STARTED
生命周期状态或更高的状态时,可以添加、替换或移除 Fragment。
- 可以在同一 Activity 或多个 Activity 中使用同一 Fragment 类的多个实例。
多个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/tv" |
| android:layout_width="match_parent" |
| android:layout_height="40dp" |
| android:text="@string/hello_blank_fragment" /> |
| |
| <Button |
| android:layout_width="match_parent" |
| android:layout_height="40dp" |
| android:id="@+id/btn" |
| android:text="按钮"/> |
| |
| </LinearLayout> |
| <?xml version="1.0" encoding="utf-8"?> |
| <LinearLayout android:layout_height="match_parent" |
| android:layout_width="match_parent" |
| xmlns:tools="http://schemas.android.com/tools" |
| android:orientation="vertical" |
| tools:context=".MainActivity" |
| xmlns:android="http://schemas.android.com/apk/res/android"> |
| |
| <fragment |
| android:id="@+id/fragment1" |
| android:name="com.example.myfragment1.BlankFragment1" |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" |
| android:layout_weight="1"/> |
| |
| <fragment |
| android:id="@+id/fragment2" |
| android:name="com.example.myfragment1.BlankFragment2" |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" |
| android:layout_weight="2"/> |
| |
| </LinearLayout> |
| package com.example.myfragment1; |
| |
| import android.os.Build; |
| import android.os.Bundle; |
| |
| import androidx.fragment.app.Fragment; |
| |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.Button; |
| import android.widget.TextView; |
| |
| 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, null); |
| } |
| textView = root.findViewById(R.id.tv); |
| button = root.findViewById(R.id.btn); |
| |
| button.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| textView.setText("被点击了"); |
| } |
| }); |
| |
| return root; |
| } |
| } |
动态添加fragment
-
创建一个待处理的fragment
-
获取FragmentManager,通常用getSupportFragmentManager()
-
开启一个事务transaction,一般调用fragmentManager的beginTransaction()
-
使用transaction进行fragment替换
-
提交事务
-
| Transaction |
| #将一个fragment实例添加到Activity里面指定id的容器中 |
| add(Fragment fragment, String tag) |
| add(int containerViewId, Fragment fragment) |
| add(int containerViewId, Fragment fragment, String tag); |
| #将一个fragment实例从FragmentManager的FragmentList中移除 |
| remove(Fragment fragment); |
| #只控制Fragment的隐藏 |
| hide(Fragment fragment) |
| #只控制Fragment的显示 |
| show(Fragment fragment) |
| #清除视图,从containerid指定的Added列表移除,FragmentList依然保留 |
| detach(Fragment fragment) |
| #创建视图,添加到containerid指定的Added列表,FragmentList依然保留 |
| attach(Fragment fragment) |
| #替换containerViewId中的fragment,它会把containerViewId中所有fragment删除,然后添加当前的fragment |
| replace(int containerViewId, Fragment fragment) |
| replace(int containerViewId, Fragment fragment, String tag) |
| <?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"> |
| |
| <Button |
| android:id="@+id/btn1" |
| android:layout_width="match_parent" |
| android:layout_height="wrap_content" |
| android:text="change"/> |
| |
| <Button |
| android:id="@+id/btn2" |
| android:layout_width="match_parent" |
| android:layout_height="wrap_content" |
| android:text="replace"/> |
| |
| <FrameLayout |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" |
| android:background="#ffff00" |
| android:id="@+id/fl"/> |
| |
| |
| </LinearLayout> |
| package com.example.myfragment2; |
| |
| import androidx.appcompat.app.AppCompatActivity; |
| import androidx.fragment.app.Fragment; |
| import androidx.fragment.app.FragmentManager; |
| import androidx.fragment.app.FragmentTransaction; |
| |
| import android.os.Bundle; |
| import android.view.View; |
| import android.widget.Button; |
| import android.widget.Toast; |
| |
| public class MainActivity extends AppCompatActivity implements View.OnClickListener{ |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_main); |
| |
| Button button1 = findViewById(R.id.btn1); |
| Button button2 = findViewById(R.id.btn2); |
| button1.setOnClickListener(this); |
| button2.setOnClickListener(this); |
| } |
| |
| @Override |
| public void onClick(View view) { |
| switch (view.getId()){ |
| case R.id.btn1: |
| |
| |
| |
| Bundle bundle = new Bundle(); |
| bundle.putString("haha", "xixi"); |
| BlankFragment1 blankFragment1 = new BlankFragment1(); |
| blankFragment1.setArguments(bundle); |
| |
| |
| blankFragment1.setFragmentCallback(new IFragmentCallback() { |
| @Override |
| public void sendMsgToActivity(String str) { |
| Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); |
| } |
| |
| @Override |
| public String getMsgFromActivity() { |
| return "发送给Fragment的"; |
| } |
| }); |
| |
| replaceFragment(blankFragment1); |
| break; |
| case R.id.btn2: |
| replaceFragment(new ItemFragment()); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| |
| private void replaceFragment(Fragment fragment) { |
| FragmentManager fragmentManager = getSupportFragmentManager(); |
| |
| FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); |
| |
| fragmentTransaction.replace(R.id.fl, fragment); |
| |
| |
| fragmentTransaction.addToBackStack(null); |
| |
| fragmentTransaction.commit(); |
| } |
| } |
activity与fragment通信
原生方法:Bundle
| case R.id.btn1: |
| |
| |
| |
| Bundle bundle = new Bundle(); |
| bundle.putString("haha", "xixi"); |
| BlankFragment1 blankFragment1 = new BlankFragment1(); |
| blankFragment1.setArguments(bundle); |
| |
| replaceFragment(blankFragment1); |
| break; |
| |
| Bundle bundle = this.getArguments(); |
| String str = bundle.getString("haha"); |
| Log.e("wmj", "value=" + str); |
接口方案
| package com.example.myfragment2; |
| |
| public interface IFragmentCallback { |
| void sendMsgToActivity(String str); |
| String getMsgFromActivity(); |
| } |
| case R.id.btn1: |
| |
| |
| |
| Bundle bundle = new Bundle(); |
| bundle.putString("haha", "xixi"); |
| BlankFragment1 blankFragment1 = new BlankFragment1(); |
| blankFragment1.setArguments(bundle); |
| |
| |
| blankFragment1.setFragmentCallback(new IFragmentCallback() { |
| @Override |
| public void sendMsgToActivity(String str) { |
| Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show(); |
| } |
| |
| @Override |
| public String getMsgFromActivity() { |
| return "发送给Fragment的"; |
| } |
| }); |
| |
| replaceFragment(blankFragment1); |
| break; |
| package com.example.myfragment2; |
| |
| 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; |
| import android.widget.Toast; |
| |
| |
| public class BlankFragment1 extends Fragment { |
| |
| private View rootview; |
| |
| private IFragmentCallback fragmentCallback; |
| |
| public void setFragmentCallback(IFragmentCallback fragmentCallback) { |
| this.fragmentCallback = fragmentCallback; |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| |
| Bundle bundle = this.getArguments(); |
| String str = bundle.getString("haha"); |
| Log.e("wmj", "value=" + str); |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| if(rootview == null){ |
| rootview = inflater.inflate(R.layout.fragment_blank1, container, false); |
| } |
| Button button = rootview.findViewById(R.id.btn3); |
| button.setOnClickListener(new View.OnClickListener() { |
| @Override |
| public void onClick(View view) { |
| |
| String str = fragmentCallback.getMsgFromActivity(); |
| Toast.makeText(BlankFragment1.this.getContext(), str, Toast.LENGTH_SHORT).show(); |
| } |
| }); |
| return rootview; |
| } |
| |
| @Override |
| public void onResume() { |
| |
| super.onResume(); |
| } |
| } |
其他方案:eventBus,LiveData
Fragment生命周期


- 创建:onAttach() -> onCreate() -> onCreateView() -> onActivityCreated() -> onStart() -> onResume()
- 按下主屏键:onPause() -> onStop()
- 重新打开:onStart() -> onResume()
- 按下后退键:onPause() -> onStop() -> onDestroyView() -> onDestroy() -> onDetach()
| <?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="55dp" |
| android:background="#B0C4DE"> |
| |
| <LinearLayout |
| android:layout_width="0dp" |
| android:layout_height="match_parent" |
| android:layout_weight="1" |
| android:layout_gravity="center" |
| android:gravity="center" |
| android:orientation="vertical" |
| android:id="@+id/tab_weixin"> |
| |
| <ImageView |
| android:layout_width="32dp" |
| android:layout_height="32dp" |
| android:background="@drawable/tab_weixin" |
| android:id="@+id/iv_weixin"/> |
| <TextView |
| android:layout_width="32dp" |
| android:layout_height="wrap_content" |
| android:gravity="center" |
| android:text="微信" |
| android:id="@+id/tv_weixin"/> |
| |
| </LinearLayout> |
| |
| <LinearLayout |
| android:layout_width="0dp" |
| android:layout_height="match_parent" |
| android:layout_weight="1" |
| android:layout_gravity="center" |
| android:gravity="center" |
| android:orientation="vertical" |
| android:id="@+id/tab_pay"> |
| |
| <ImageView |
| android:layout_width="32dp" |
| android:layout_height="32dp" |
| android:background="@drawable/tab_pay" |
| android:id="@+id/iv_pay"/> |
| <TextView |
| android:layout_width="32dp" |
| android:layout_height="wrap_content" |
| android:gravity="center" |
| android:text="支付" |
| android:id="@+id/tv_pay"/> |
| |
| </LinearLayout> |
| |
| <LinearLayout |
| android:layout_width="0dp" |
| android:layout_height="match_parent" |
| android:layout_weight="1" |
| android:layout_gravity="center" |
| android:gravity="center" |
| android:orientation="vertical" |
| android:id="@+id/tab_weixin1"> |
| |
| <ImageView |
| android:layout_width="32dp" |
| android:layout_height="32dp" |
| android:background="@drawable/tab_weixin1" |
| android:id="@+id/iv_weixin1"/> |
| <TextView |
| android:layout_width="32dp" |
| android:layout_height="wrap_content" |
| android:gravity="center" |
| android:text="微" |
| android:id="@+id/tv_weixin1"/> |
| |
| </LinearLayout> |
| |
| <LinearLayout |
| android:layout_width="0dp" |
| android:layout_height="match_parent" |
| android:layout_weight="1" |
| android:layout_gravity="center" |
| android:gravity="center" |
| android:orientation="vertical" |
| android:id="@+id/tab_weixin2"> |
| |
| <ImageView |
| android:layout_width="32dp" |
| android:layout_height="32dp" |
| android:background="@drawable/tab_weixin2" |
| android:id="@+id/iv_weixin2"/> |
| <TextView |
| android:layout_width="32dp" |
| android:layout_height="wrap_content" |
| android:gravity="center" |
| android:text="信" |
| android:id="@+id/tv_weixin2"/> |
| |
| </LinearLayout> |
| |
| </LinearLayout> |
| <?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"> |
| |
| |
| <TextView |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" |
| android:gravity="center" |
| android:textSize="36sp" |
| android:id="@+id/tv" |
| android:text="@string/hello_blank_fragment" /> |
| |
| </FrameLayout> |
| <?xml version="1.0" encoding="utf-8"?> |
| <LinearLayout android:layout_height="match_parent" |
| android:layout_width="match_parent" |
| android:orientation="vertical" |
| xmlns:android="http://schemas.android.com/apk/res/android"> |
| |
| <androidx.viewpager2.widget.ViewPager2 |
| android:layout_width="match_parent" |
| android:layout_height="0dp" |
| android:layout_weight="1" |
| android:id="@+id/vp"/> |
| |
| <include layout="@layout/bottom_layout"></include> |
| |
| </LinearLayout> |
| <?xml version="1.0" encoding="utf-8"?> |
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> |
| <item android:drawable="@drawable/weixin2" android:state_selected="true"/> |
| <item android:drawable="@drawable/weixin1"/> |
| </selector> |
| package com.example.mywechat; |
| |
| import android.os.Bundle; |
| |
| import androidx.fragment.app.Fragment; |
| |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.TextView; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class BlankFragment extends Fragment { |
| |
| private static final String ARG_TEXT = "param1"; |
| private View rootView; |
| private String mTextString; |
| |
| public BlankFragment() { |
| |
| } |
| |
| public static BlankFragment newInstance(String param1) { |
| BlankFragment fragment = new BlankFragment(); |
| Bundle args = new Bundle(); |
| args.putString(ARG_TEXT, param1); |
| fragment.setArguments(args); |
| return fragment; |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| if (getArguments() != null) { |
| mTextString = getArguments().getString(ARG_TEXT); |
| } |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| if(rootView == null){ |
| rootView = inflater.inflate(R.layout.fragment_blank, container, false); |
| } |
| initView(); |
| return rootView; |
| } |
| |
| private void initView() { |
| TextView textView = rootView.findViewById(R.id.tv); |
| textView.setText(mTextString); |
| } |
| } |
| package com.example.mywechat; |
| |
| import androidx.appcompat.app.AppCompatActivity; |
| import androidx.fragment.app.Fragment; |
| import androidx.viewpager2.widget.ViewPager2; |
| |
| import android.os.Bundle; |
| import android.view.View; |
| import android.widget.ImageView; |
| import android.widget.LinearLayout; |
| import android.widget.TextView; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class MainActivity extends AppCompatActivity implements View.OnClickListener{ |
| |
| private ViewPager2 viewPager; |
| private LinearLayout llweixin, llweixin1, llweixin2, llpay; |
| private ImageView ivweixin, ivweixin1, ivweixin2, ivpay, ivCurrent; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.activity_main); |
| |
| initPager(); |
| initTabView(); |
| } |
| |
| private void initPager() { |
| List<Fragment> fragments = new ArrayList<>(); |
| fragments.add(BlankFragment.newInstance("微信")); |
| fragments.add(BlankFragment.newInstance("通讯录")); |
| fragments.add(BlankFragment.newInstance("发现")); |
| fragments.add(BlankFragment.newInstance("我")); |
| |
| viewPager = findViewById(R.id.vp); |
| MyFragmentPagerAdapter myFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), getLifecycle(), fragments); |
| viewPager.setAdapter(myFragmentPagerAdapter); |
| viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { |
| @Override |
| public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { |
| super.onPageScrolled(position, positionOffset, positionOffsetPixels); |
| } |
| |
| @Override |
| public void onPageSelected(int position) { |
| super.onPageSelected(position); |
| changeTab(position); |
| } |
| |
| @Override |
| public void onPageScrollStateChanged(int state) { |
| super.onPageScrollStateChanged(state); |
| } |
| }); |
| } |
| |
| private void changeTab(int position) { |
| ivCurrent.setSelected(false); |
| switch (position){ |
| case R.id.tab_weixin: |
| viewPager.setCurrentItem(0); |
| case 0: |
| ivweixin.setSelected(true); |
| ivCurrent = ivweixin; |
| break; |
| case R.id.tab_pay: |
| viewPager.setCurrentItem(1); |
| case 1: |
| ivpay.setSelected(true); |
| ivCurrent = ivpay; |
| break; |
| case R.id.tab_weixin1: |
| viewPager.setCurrentItem(2); |
| case 2: |
| ivweixin1.setSelected(true); |
| ivCurrent = ivweixin1; |
| break; |
| case R.id.tab_weixin2: |
| viewPager.setCurrentItem(3); |
| case 3: |
| ivweixin2.setSelected(true); |
| ivCurrent = ivweixin2; |
| break; |
| } |
| } |
| |
| private void initTabView(){ |
| llweixin = findViewById(R.id.tab_weixin); |
| llweixin.setOnClickListener(this); |
| llweixin1 = findViewById(R.id.tab_weixin1); |
| llweixin1.setOnClickListener(this); |
| llweixin2 = findViewById(R.id.tab_weixin2); |
| llweixin2.setOnClickListener(this); |
| llpay = findViewById(R.id.tab_pay); |
| llpay.setOnClickListener(this); |
| ivweixin = findViewById(R.id.iv_weixin); |
| ivweixin1 = findViewById(R.id.iv_weixin1); |
| ivweixin2 = findViewById(R.id.iv_weixin2); |
| ivpay = findViewById(R.id.iv_pay); |
| |
| llweixin.setSelected(true); |
| ivCurrent = ivweixin; |
| } |
| |
| @Override |
| public void onClick(View view) { |
| changeTab(view.getId()); |
| } |
| } |
- MyFragmentPagerAdapter.java
| package com.example.mywechat; |
| |
| import androidx.annotation.NonNull; |
| import androidx.fragment.app.Fragment; |
| import androidx.fragment.app.FragmentManager; |
| import androidx.lifecycle.Lifecycle; |
| import androidx.viewpager2.adapter.FragmentStateAdapter; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class MyFragmentPagerAdapter extends FragmentStateAdapter { |
| |
| private List<Fragment> fragmentList = new ArrayList<>(); |
| |
| public MyFragmentPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, List<Fragment> fragments) { |
| super(fragmentManager, lifecycle); |
| fragmentList = fragments; |
| } |
| |
| @NonNull |
| @Override |
| public Fragment createFragment(int position) { |
| return fragmentList.get(position); |
| } |
| |
| @Override |
| public int getItemCount() { |
| return fragmentList.size(); |
| } |
| } |
与fragment通信
使用ViewModel
fragment和activity
| viewModel = new ViewModelProvider(this).get(CityViewModel.class); |
| |
| |
| |
| |
| |
| |
| viewModel = new ViewModelProvider(requireActivity()).get(CityViewModel.class); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步