Android UI——碎片fragment
碎片是一种嵌入在活动中的UI片段,它能使程序更加合理和充分地利用大屏的空间,因而在平板上地应用更加广泛。
碎片的简单用法:
新建一个项目unit4,分别建立左侧碎片和右侧碎片。
左侧碎片中只放置一个按钮,编写left_fragment.xml:
<?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="vertical">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Button"/>
</LinearLayout>
右侧碎片只放置一个TextView显示文字,编写right_fragment.xml:
<?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="vertical"
android:background="#00ff00">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="This is right fragment"
android:textSize="20sp"/>
</LinearLayout>
我们将布局的背景颜色换成了绿色,并且放了一段文字。
接下来我们定义两个类,LeftFragment和RightFragment都继承Fragment,让他们分别将定义好的两个布局文件加载出来:
LeftFragment:
package com.example.unit4;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
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;
}
}
RightFragment:
package com.example.unit4;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
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;
}
}
接下来我们为了让两个碎片在主活动中显示,修改activity_main.xml地代码:
<?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/left_fragment"
android:name="com.example.unit4.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<fragment
android:id="@+id/right_fragment"
android:name="com.example.unit4.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
这样我们就可以在主活动中显示出来我们定义的左侧碎片和右侧碎片,我们运行下程序看看:

动态添加碎片
接着之上的内容,我们给左侧碎片的按钮一个点击事件,点击后我们更换右侧的碎片,知道目的以后我们来实现它:
首先我们定义一个新的右侧碎片来代替原先的右侧碎片another_right_fragment:
<?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="vertical"
android:background="#fff000">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:text="This is another right fragment"/>
</LinearLayout>
同样的我们需要定义一个类AnotherRightFragment类来加载上面的布局:
package com.example.unit4;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class AnotherRightFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.another_right_fragment,container,false);
return view;
}
}
为了能更换右侧的碎片,我们需要将主活动布局中的右侧由原先的fragment改为Layout,这里我们用到的是帧布局FrameLayout,因为我们只需要在布局中假如一个碎片,这是最简单的布局,我们当然用它。
<?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/left_fragment"
android:name="com.example.unit4.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<FrameLayout
android:id="@+id/right_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
此时我们就需要修改MainActivity中的代码,为button注册监听器,并且要在点击后更换碎片。
package com.example.unit4;
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.FrameLayout;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
replaceFragment(new RightFragment());
button.setOnClickListener(this);
replaceFragment(new RightFragment());
}
@Override
public void onClick(View view) {
switch(view.getId()){
case R.id.button :
replaceFragment(new AnotherRightFragment());
break;
default:
break;
}
}
private void replaceFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.right_layout,fragment);
transaction.addToBackStack(null);
transaction.commit();
}
}
动态添加碎片可以分为五步:
(1) 创建碎片实例
(2) 获取FragmentManager , 在活动中可以直接调用getSupportFragmentManager()完成。
(3) 开启一个事务,通过调用beginTransaction()方法开启。
(4) 像容器中添加或调换碎片,一般用replace方法完成, 需要传入两个参数,一个是容器的id,一个是待添加的碎片实例。
(5) 提交事务,调用commit()方法即可。
可以看到我们自定义了一个reolaceFragment()方法,这里面是完成更换碎片的步骤,然后我们用replaceFragment(new RightFragment())在加载布局时就将原右侧碎片加载进来,随后我们为左侧碎片的按钮注册了点击事件,点击后就调用replaceFragment()方法更换碎片。
接下来重启程序,点击按钮看一下效果:
这里还有一个addToBackStack()方法我们还没有说到,这个方法适用于将一个事务添加到返回栈中,他可以接受一个名字用于描述返回栈的状态,我们填入null就可以了。如果加上这句话,我们再更换碎片后需要按下三次Back才能退出程序,而如果不添加这个方法我们按一下Back就退出程序了。
碎片如何与活动进行通信
虽然碎片嵌入在活动之中,但是他俩的关系并没有那么亲密,如果我们想在碎片中调用活动的方法,或者想在活动中调用碎片的方法,应该如何实现呢?
其实我们可以调用Fragment类中的findFragmentById()方法来实现在活动中调用碎片的方法,例如:
Fragment frgment = (Fragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
这样我们就可以在活动中获取到碎片的实例,然后就可以在是实例中调用各种方法。
还有如何在碎片中获取到活动的实例呢?
其实更简单,我们直接调用getActivity()方法就可以获取到当前活动的实例,然后就可以轻松地调用活动里的方法啦!
MainActivity activity = (MainActivity) getActivity();