🛸~~ 🚁🚁🚁🛩️🛩️🛩️|

n1ce2cv

园龄:5年2个月粉丝:4关注:1

Fragment

Fragment

  • Fragment表示应用界面中可重复使用的一部分。Fragment 定义和管理自己的布局,具有自己的生命周期,并且可以处理自己的输入事件。Fragment 不能独立存在,而是必须由 Activity 或另一个 Fragment 托管。Fragment 的视图层次结构会成为宿主的视图层次结构的一部分,或附加到宿主的视图层次结构。
  • activity_main.xml中的fragment必须有id
  • 当 Activity 处于 STARTED 生命周期状态或更高的状态时,可以添加、替换或移除 Fragment。
  • 可以在同一 Activity 或多个 Activity 中使用同一 Fragment 类的多个实例。

多个fragment

  • fragment1.xml
<?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">
<!-- TODO: Update blank fragment layout -->
<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>
  • activity_main.xml
<?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>
  • BlankFragment1.java
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

  1. 创建一个待处理的fragment

  2. 获取FragmentManager,通常用getSupportFragmentManager()

  3. 开启一个事务transaction,一般调用fragmentManager的beginTransaction()

  4. 使用transaction进行fragment替换

  5. 提交事务

  6. 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)
  • activity_main.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"
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>
  • MainActivity.java
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:
// activity 与 fragment通信
// 原生方法:Bundle
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;
}
}
// 动态切换fragment
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
// 开启一个事务
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// 替换containerViewId中的fragment,它会把containerViewId中所有fragment删除,然后添加当前的fragment
fragmentTransaction.replace(R.id.fl, fragment);
// 放到同一个栈里,点返回时显示上一个fragment
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}

activity与fragment通信

原生方法:Bundle

case R.id.btn1:
// activity 与 fragment通信
// 原生方法:Bundle
Bundle bundle = new Bundle();
bundle.putString("haha", "xixi");
BlankFragment1 blankFragment1 = new BlankFragment1();
blankFragment1.setArguments(bundle);
replaceFragment(blankFragment1);
break;
// 在fragment中获取当前fragment的arguments
Bundle bundle = this.getArguments();
String str = bundle.getString("haha");
Log.e("wmj", "value=" + str);

接口方案

  • IFragmentCallback.java
package com.example.myfragment2;
public interface IFragmentCallback {
void sendMsgToActivity(String str);
String getMsgFromActivity();
}
  • MainActivity.java
case R.id.btn1:
// activity 与 fragment通信
// 原生方法:Bundle
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;
  • BlankFragment1.java
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;// 用来接收activity中的接口型对象
public void setFragmentCallback(IFragmentCallback fragmentCallback) {
this.fragmentCallback = fragmentCallback;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 在fragment中获取当前fragment的arguments
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) {
// fragmentCallback.sendMsgToActivity("发送给Activity");
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生命周期

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

Fragment和ViewPager滑动效果

  • buttom_layout.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="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>
  • fragment_blank.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:gravity="center"
android:textSize="36sp"
android:id="@+id/tv"
android:text="@string/hello_blank_fragment" />
</FrameLayout>
  • activity_main.xml
<?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>
  • tab_weixin.xml
<?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>
  • BlankFragment.java
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() {
// Required empty public constructor
}
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);
}
}
  • MainActivity.java
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

  • Activity中
viewModel = new ViewModelProvider(this).get(CityViewModel.class);
  • Fragment中
/**
* MainActivity用作MainActivity和WeatherDetailFragment中的范围,因此为它们提供了相同的 ViewModel。
* 如果WeatherDetailFragment将自身用作范围,即viewModel = new ViewModelProvider(this).get(CityViewModel.class);
* 会为其提供与MainActivity不同的ViewModel。
*/
// viewModel = new ViewModelProvider(this).get(CityViewModel.class); // 不同的viewmodel
viewModel = new ViewModelProvider(requireActivity()).get(CityViewModel.class);

本文作者:n1ce2cv

本文链接:https://www.cnblogs.com/sprinining/p/14955032.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   n1ce2cv  阅读(148)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起