介绍
Fragment 是 Android 3.0 新增的概念,其中文意思是碎片,它与 Activity 十分相似,用来在一个Activity 中描述一些行为或一部分用户界面。使用多个 Fragment 可以在一个单独的 Activity 中建立多个 UI 面板,也可以在多个 Activity 中重用 Fragment。例如,微信主界面就相当于一个 Activity,在这个 Activity 中包含多个 Fragment,其中"微信" "通讯录" "发现" "我"这 4 个功能界面,每一个功能界面就相当于一个 Fragment,它们之间可以随意切换。
生命周期
和 Activity 一样,Fragment 也有自己的生命周期。一个 Fragment 必须被嵌入到一个 Activity 中,它的生命周期直接受其所属的宿主 Activity 的生命周期影响。例如,当 Activity 被暂停时,其中的所有 Fragment 也被暂停;当 Activity 被销毁时,所有隶属于它的 Fragment 也将被销毁。然而,当一个 Activity 正在运行时(处于 resumed 状态),可以单独地对每一个 Fragment 进行操作,如添加或删除等。Fragment 完整的生命周期如图所示。
例子
模拟微信界面功能
编写wechat_fragment布局文件
在 res/layout 目录下创建一个名称为 wechat_fragment.xml 的布局文件,改为相对布局管理器,然后在该布局文件中添加一个 ImageView 组件,用于存放要显示的图片。(接着依次建立message_fragment.xml、find_fragment.xml、me_fragment.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">
<ImageView
android:id="@+id/image1"
android:layout_width="300dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:src="@drawable/img01" />
</RelativeLayout>
编写WeChat_Fragment
创建一个名称为“WeChat_Fragment”的类,让这个类继承 Fragment 类,并且重写 onCreateView() 方法,然后为 WeChat_Fragment 添加 wechat_fragment.xml 布局文件,具体代码如下:(同样依次创建Message_Fragment、Find_Fragment、Me_Fragment)
注意:这里我引入的是以下包
import androidx.fragment.app.Fragment;
public class WeChat_Fragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.wechat_fragment,null);
return view;
}
}
编写activity_we_chat布局文件
先在values文件夹下的colors.xml颜色配置文件中添加transparent
(透明的)颜色#00XXXXXX
<!--取消RadioButton的按压效果-->
android:background="@color/transparent"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_linera"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></FrameLayout>
<RadioGroup
android:id="@+id/rg_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<!--微信图标-->
<RadioButton
android:id="@+id/rb_wechat"
style="@style/WeChatButtonStyle"
android:drawableTop="@drawable/selector_wechat"
android:background="@color/transparent"
android:text="微信" />
<!--通讯录图标-->
<RadioButton
android:id="@+id/rb_message"
style="@style/WeChatButtonStyle"
android:drawableTop="@drawable/selector_message"
android:text="通讯录" />
<!--发现图标-->
<RadioButton
android:id="@+id/rb_find"
style="@style/WeChatButtonStyle"
android:drawableTop="@drawable/selector_find"
android:text="发现" />
<!--我图标-->
<RadioButton
android:id="@+id/rb_me"
style="@style/WeChatButtonStyle"
android:drawableTop="@drawable/selector_me"
android:text="我" />
</RadioGroup>
</LinearLayout>
设置WeChatButtonStyle
<!-- <item name="android:drawablePadding">3dp</item>-->
<style name="WeChatButtonStyle">
<!-- Customize your theme here. -->
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_weight">1</item>
<item name="android:button">@null</item>
<item name="android:textColor">@drawable/selector_wechat_text</item>
<item name="android:textSize">10sp</item>
<item name="android:gravity">center</item>
</style>
设置selector_wechat_text
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/light_black" android:state_checked="false"></item>
<item android:color="@color/light_green" android:state_checked="true"></item>
</selector>
设置按钮的按压效果
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="@drawable/wechat01"/>
<item android:state_checked="true" android:drawable="@drawable/wechat001"/>
</selector>
编写WeChatActivity
导入包不同,使用的方法不同
//导入包:
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
//对应方法:
FragmentManager fm = getFragmentManager();
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
//对应方法:
FragmentManager fm =getSupportFragmentManager();
在hideOthersFragment方法中之所以要为mTransaction重新获取,是因为我这里的事务是全局的变量,只能commit一次,否则会出现以下错误:
java.lang.IllegalStateException: commit already called
public class WeChatActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
private RadioGroup mRg;
private List<Fragment> mFragments = new ArrayList<>();
private WeChatFragment mWeChatFragment;
private MessageFragment mMessageFragment;
private FindFragment mFindFragment;
private MeFragment mMeFragment;
private FragmentManager mSupportFragmentManager;
private FragmentTransaction mTransaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_we_chat);
init();
setListeners();
}
private void init() {
mRg = (RadioGroup) findViewById(R.id.rg_main);
mSupportFragmentManager = getSupportFragmentManager();
mTransaction = mSupportFragmentManager.beginTransaction();
mWeChatFragment = new WeChatFragment();
mMessageFragment = new MessageFragment();
mFindFragment = new FindFragment();
mMeFragment = new MeFragment();
mFragments.add(mWeChatFragment);
mFragments.add(mMessageFragment);
mFragments.add(mFindFragment);
mFragments.add(mMeFragment);
mTransaction.add(R.id.frameLayout,mWeChatFragment);
mTransaction.add(R.id.frameLayout,mMessageFragment);
mTransaction.add(R.id.frameLayout,mFindFragment);
mTransaction.add(R.id.frameLayout,mMeFragment);
mTransaction.commit();
mRg.check(R.id.rb_wechat);//设置默认选中项
hideOthersFragment(mWeChatFragment);//一开始显示wechat的界面
}
private void setListeners(){
mRg.setOnCheckedChangeListener(this);
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.rb_wechat:
hideOthersFragment(mWeChatFragment);
break;
case R.id.rb_message:
hideOthersFragment(mMessageFragment);
break;
case R.id.rb_find:
hideOthersFragment(mFindFragment);
break;
case R.id.rb_me:
hideOthersFragment(mMeFragment);
break;
}
}
//显示传入fragment的界面,隐藏其他的
private void hideOthersFragment(Fragment showFragment) {
mTransaction = mSupportFragmentManager.beginTransaction();
for (Fragment fragment : mFragments) {
if (showFragment.equals(fragment)) {
mTransaction.show(fragment);
} else {
mTransaction.hide(fragment);
}
}
mTransaction.commit();
}
}