碎片
一种可以嵌入活动当中的UI片段,使程序更加合理充分地利用大屏幕空间。在平板上使用广泛
简单实例
左布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/bt_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"/>
</LinearLayout>
右布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffcc00"
>
<TextView
android:id="@+id/tv_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is right fragment"
android:textSize="20sp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
右额外布局(点击左布局按钮生产)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffcc">
<TextView
android:id="@+id/tv_textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is another right fragment"
android:textSize="20sp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
左布局的碎片类
public class LeftFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.left_fragment,container,false);
return view;
}
}
右布局碎片类
public class RightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.right_fragment,container,false);
return view;
}
}
右额外布局的碎片类,类似上两者
MainActivity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<fragment
android:id="@+id/f_left"
android:name="cn.ywrby.fragmenttext.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="@+id/fl_fragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
package cn.ywrby.fragmenttext;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button=findViewById(R.id.bt_button);
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
@Override
public void onClick(View v) {
switch (v.getId()){
case (R.id.bt_button):
replaceFragment(new AnotherRightFragment());
break;
default:
break;
}
}
private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager=getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fl_fragment,fragment);
fragmentTransaction.commit();
}
}
按动按钮前
按动后
动态添加碎片的步骤
- 创建待添加碎片的实例(FrameLayout…)
- 获取FragmentManager,在活动中直接通过调用getSupportFragmentManager()方法获取
- 开启事务,调用FragmentManager的beginTransaction方法(得到事务类:FragmentTransaction)
- 像容器中添加或替换碎片,一般利用事务类FragmentTransaction的replace方法,传入容器ID和待添加的碎片实例
- 提交事务,调用FragmentTransaction的commit方法
模拟返回栈
对碎片进行动态添加并不会生成新的活动进入返回栈中,所以类似刚才实现的实例,在按动按钮变色后,再按返回键back,程序会直接退出,而不是返回到最开始的黄色状态,所以,要模拟这种添加到返回栈的效果,就可以用到FragmentTransaction中的addToBackStack()方法
修改上述代码:
private void replaceFragment(Fragment fragment){
FragmentManager fragmentManager=getSupportFragmentManager();
FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fl_fragment,fragment);
fragmentTransaction.addToBackStack(null); //需要传入一个名字用于描述返回栈状态,一般null即可
fragmentTransaction.commit();
}
碎片与活动之间的通信
在活动中与碎片进行通信,FragementManager提供了类似findViewByID的方法findFragmentByID
在碎片中与活动进行通信,可以调用getActivity()方法获取与当前碎片相关的活动
动态加载布局技巧
限定符(Qualifiers)
可以帮助我们在运行时判断应该使用双叶模式还是单页模式
在res文件夹下新建的layout-large文件夹中新建同名的activity_main布局,重写其中内容,实现通过large限定符动态加载布局
layout文件夹中布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/f_left"
android:name="cn.ywrby.fragmenttext.LeftFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
layout-large文件夹中布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/f_left"
android:name="cn.ywrby.fragmenttext.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
/>
<fragment
android:id="@+id/f_right"
android:name="cn.ywrby.fragmenttext.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
/>
</LinearLayout>
最终效果成功实现在平板电脑上运行双页模式,在手机上运行单页模式的动态加载布局
常见限定符
屏幕特征 | 限定符 | 描述 |
---|---|---|
大小 | small | 小屏幕设备 |
大小 | normal | 中等屏幕大小设备 |
大小 | large | 大屏幕设备 |
大小 | xlarge | 超大屏幕设备 |
分辨率 | lapi | 低分辨率设备120dpi以下 |
分辨率 | mdpi | 中等分辨率120-160dpi |
分辨率 | hdpi | 高分辨率160-240dpi |
分辨率 | xhdpi | 超高分辨率|240-320dpi |
分辨率 | xxhdpi | 超超高分辨率|320-480dpi |
方向 | land | 横屏设备 |
方向 | port | 竖屏设备 |
另外,还可以使用最小宽度限定符,限定符格式为
sw+分辨率大小+dp