不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵!
Fragment的两种切换方式
- 两种方式为
add
和replace
add
方式和replace
方式区别:add
方式每次切换不同的Fragment
的时候,不会重新创建,都是恢复上次的。如今大多数的app基本都是采用这种方式。replace
方式每次切换不同的Fragment
,都会重新创建一个Fragment
。
replace
使用三个布局作为底部按钮,用一个布局占据放置Fragment的位置。
- 布局-------activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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.constraintlayout.widget.ConstraintLayout
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/constraintLayout2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout"
android:layout_width="0dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/constraintLayout2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="消息"
android:textColor="@color/main_color"
android:textSize="25sp"
android:typeface="serif"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout2"
android:layout_width="0dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/constraintLayout3"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/constraintLayout">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="联系人"
android:textColor="@color/main_color"
android:textSize="25sp"
android:typeface="serif"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout3"
android:layout_width="0dp"
android:layout_height="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/constraintLayout2">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="动态"
android:textColor="@color/main_color"
android:textSize="25sp"
android:typeface="serif"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
创建三个Fragment,并且在每个Fragment布局中加入文本控件,设置文本点击事件,来判断Fragment是否重建。
-
三个Fragment相似,此处以MessageFragment为例。
- 布局-------fragment_message.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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=".MessageFragment"> <TextView android:id="@+id/msgTextView" android:layout_width="match_parent" android:layout_height="match_parent" android:text="消息" android:gravity="center" android:typeface="monospace" android:textColor="#000000" android:textSize="50sp"/> </androidx.constraintlayout.widget.ConstraintLayout>
- 逻辑-------MessageFragment
package com.hnucm.androidfragment; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class MessageFragment extends Fragment { //定义控件 private TextView textView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //得到fragment中的布局文件 View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_message,container,false); //找到布局中的控件 textView = (TextView) view.findViewById(R.id.msgTextView); //设置点击文本变化来判断是否重建fragment textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { textView.setText("我变了-" + textView.getText().toString()); } }); //返回view return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); } }
在MainActivity中主要实现采用replace方式的切换以及底下文字颜色点击变化。
- 逻辑-------MainActivity
package com.hnucm.androidfragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//定义三个Fragment
private MessageFragment messageFragment;
private PersonFragment personFragment;
private DynamicFragment dynamicFragment;
//定义三个布局按钮
private ConstraintLayout constraintLayout;
private ConstraintLayout constraintLayout2;
private ConstraintLayout constraintLayout3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化Fragment
messageFragment = new MessageFragment();
personFragment = new PersonFragment();
dynamicFragment = new DynamicFragment();
//初始化ConstraintLayout
constraintLayout = findViewById(R.id.constraintLayout);
constraintLayout2 = findViewById(R.id.constraintLayout2);
constraintLayout3 = findViewById(R.id.constraintLayout3);
//定义三个布局
//消息布局按钮
constraintLayout.setOnClickListener(this);
//联系人布局按钮
constraintLayout2.setOnClickListener(this);
//动态布局按钮
constraintLayout3.setOnClickListener(this);
//点击消息,字体颜色变化
constraintLayout.setSelected(true);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(false);
//事务一定要提交
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,messageFragment).commit();
}
@Override
//点击事件
public void onClick(View view) {
switch(view.getId()){
//切换fragment
case R.id.constraintLayout:
//字体颜色变化
constraintLayout.setSelected(true);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(false);
//替换Fragment
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,messageFragment).commit();
break;
case R.id.constraintLayout2:
//颜色变化
constraintLayout.setSelected(false);
constraintLayout2.setSelected(true);
constraintLayout3.setSelected(false);
//切换
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,personFragment).commit();
break;
case R.id.constraintLayout3:
//颜色
constraintLayout.setSelected(false);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(true);
//切换
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,dynamicFragment).commit();
break;
}
}
}
- 颜色改变文件-------main_color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#000000" android:state_selected="false"/>
<item android:color="#397291" android:state_selected="true"/>
</selector>
只需把文字颜色设置为这个文件即可。
add
所有的都不用改,只需要改MainActivity中的逻辑即可。
将replace方法改为add方法即可。
replace方法直接替换覆盖,add方法主要是采用隐藏和显示。
- 逻辑-------MainActivity
package com.hnucm.androidfragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//定义三个Fragment
private MessageFragment messageFragment;
private PersonFragment personFragment;
private DynamicFragment dynamicFragment;
//定义三个布局按钮
private ConstraintLayout constraintLayout;
private ConstraintLayout constraintLayout2;
private ConstraintLayout constraintLayout3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化ConstraintLayout
constraintLayout = findViewById(R.id.constraintLayout);
constraintLayout2 = findViewById(R.id.constraintLayout2);
constraintLayout3 = findViewById(R.id.constraintLayout3);
//定义三个布局
//消息布局按钮
constraintLayout.setOnClickListener(this);
//联系人布局按钮
constraintLayout2.setOnClickListener(this);
//动态布局按钮
constraintLayout3.setOnClickListener(this);
//点击消息,字体颜色变化
constraintLayout.setSelected(true);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(false);
//第一次初始化默认显示第一个fragment
initMessageFragment();
}
//显示消息Fragment
private void initMessageFragment(){
//开启事务,由事务来控制Fragment
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
//初始化fragment并加入到事务中,如果为空就new一个
//if条件判断语句导致add方法无需每次新建一个Fragment
if(messageFragment == null){
//新建一个
messageFragment = new MessageFragment();
//添加进事务中,并且放置到预留的区域
fragmentTransaction.add(R.id.fragment,messageFragment);
}
//隐藏事务中所有的Fragment
hideFragment(fragmentTransaction);
//显示需要显示的Fragment
fragmentTransaction.show(messageFragment);
//提交事务,事务一定要提交,不然无效
fragmentTransaction.commit();
}
//显示联系人Fragment
private void initPersonFragment(){
//开启事务,由事务来控制Fragment
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
//初始化fragment并加入到事务中,如果为空就new一个
//if条件判断语句导致add方法无需每次新建一个Fragment
if(personFragment == null){
//新建一个
personFragment = new PersonFragment();
//添加进事务中,并且放置到预留的区域
fragmentTransaction.add(R.id.fragment,personFragment);
}
//隐藏事务中所有的Fragment
hideFragment(fragmentTransaction);
//显示需要显示的Fragment
fragmentTransaction.show(personFragment);
//提交事务,事务一定要提交,不然无效
fragmentTransaction.commit();
}
//显示动态Fragment
private void initDynamicFragment(){
//开启事务,由事务来控制Fragment
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
//初始化fragment并加入到事务中,如果为空就new一个
//if条件判断语句导致add方法无需每次新建一个Fragment
if(dynamicFragment == null){
//新建一个
dynamicFragment = new DynamicFragment();
//添加进事务中,并且放置到预留的区域
fragmentTransaction.add(R.id.fragment,dynamicFragment);
}
//隐藏事务中所有的Fragment
hideFragment(fragmentTransaction);
//显示需要显示的Fragment
fragmentTransaction.show(dynamicFragment);
//提交事务,事务一定要提交,不然无效
fragmentTransaction.commit();
}
//隐藏Fragment
private void hideFragment(FragmentTransaction fragmentTransaction){
//隐藏MessageFragment
if(messageFragment != null){
fragmentTransaction.hide(messageFragment);
}
//隐藏PersonFragment
if(personFragment != null){
fragmentTransaction.hide(personFragment);
}
//隐藏DynamicFragment
if(dynamicFragment != null){
fragmentTransaction.hide(dynamicFragment);
}
}
@Override
//点击事件
public void onClick(View view) {
switch(view.getId()){
//切换fragment
case R.id.constraintLayout:
//字体颜色变化
constraintLayout.setSelected(true);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(false);
//替换Fragment
initMessageFragment();
break;
case R.id.constraintLayout2:
//颜色变化
constraintLayout.setSelected(false);
constraintLayout2.setSelected(true);
constraintLayout3.setSelected(false);
//切换
initPersonFragment();
break;
case R.id.constraintLayout3:
//颜色
constraintLayout.setSelected(false);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(true);
//切换
initDynamicFragment();
break;
}
}
}
代码可以继续优化。
参考上述代码,我们发现initMessageFragment方法和initPersonFragment方法以及initDynamicFragment方法很相似,我们可以利用传递参数的方式写成一个函数。
就比如写一个简单工厂方法,其他的方法都是通过这个工厂去生产产生,你只需要传递参数,就可以根据不同参数返回不同的类型。
- 逻辑-------MainActivity
package com.hnucm.androidfragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
//定义三个Fragment
private MessageFragment messageFragment;
private PersonFragment personFragment;
private DynamicFragment dynamicFragment;
//定义三个布局按钮
private ConstraintLayout constraintLayout;
private ConstraintLayout constraintLayout2;
private ConstraintLayout constraintLayout3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化ConstraintLayout
constraintLayout = findViewById(R.id.constraintLayout);
constraintLayout2 = findViewById(R.id.constraintLayout2);
constraintLayout3 = findViewById(R.id.constraintLayout3);
//定义三个布局
//消息布局按钮
constraintLayout.setOnClickListener(this);
//联系人布局按钮
constraintLayout2.setOnClickListener(this);
//动态布局按钮
constraintLayout3.setOnClickListener(this);
//点击消息,字体颜色变化
constraintLayout.setSelected(true);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(false);
//第一次初始化默认显示第一个fragment
initFragment(messageFragment);
}
//生产显示不同Fragment的简单工厂方法
private void initFragment(Fragment fragment){
//开启事务来控制Fragment
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
//初始化fragment并加入到事务中,如果为空就new一个
//if条件判断语句导致add方法无需每次新建一个Fragment
if(fragment == null){
//里氏代换原则,子类都可以代替父类
//Fragment是一切Fragment的父类
//新建一个Fragment
fragment = new Fragment();
//加入到事务中,并放置在预先留好的位置
fragmentTransaction.add(R.id.fragment,fragment);
}
//隐藏所有的Fragment
hideFragment(fragmentTransaction);
//显示需要显示的Fragment
fragmentTransaction.show(fragment);
//提交事务,事务一定要提交,不然无效
fragmentTransaction.commit();
}
//隐藏Fragment
private void hideFragment(FragmentTransaction fragmentTransaction){
//隐藏MessageFragment
if(messageFragment != null){
fragmentTransaction.hide(messageFragment);
}
//隐藏PersonFragment
if(personFragment != null){
fragmentTransaction.hide(personFragment);
}
//隐藏DynamicFragment
if(dynamicFragment != null){
fragmentTransaction.hide(dynamicFragment);
}
}
@Override
//点击事件
public void onClick(View view) {
switch(view.getId()){
//切换fragment
case R.id.constraintLayout:
//字体颜色变化
constraintLayout.setSelected(true);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(false);
//替换Fragment
initFragment(messageFragment);
break;
case R.id.constraintLayout2:
//颜色变化
constraintLayout.setSelected(false);
constraintLayout2.setSelected(true);
constraintLayout3.setSelected(false);
//切换
initFragment(personFragment);
break;
case R.id.constraintLayout3:
//颜色
constraintLayout.setSelected(false);
constraintLayout2.setSelected(false);
constraintLayout3.setSelected(true);
//切换
initFragment(dynamicFragment);
break;
}
}
}
想法具有可实行性,但是具体的新建还是有问题,出来的是一个初始Fragment,后续继续修改。