Android——Fragment(碎片)
对于碎片的用法,本人认为最重要的就是动态加载碎片。以及碎片和活动之间进行通信。下面的例子将展示如何动态加载碎片以及如何碎片与活动进行通信。
首先要大家可以将碎片理解成和活动具有类似的功能,甚至可以将其想象成一个活动。
首先我们编写activity_main代码,代码如下:
<?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"
tools:context=".MainActivity"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="添加碎片" />
<TextView
android:id="@+id/text_get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/btn"
android:text="无"
android:textSize="20sp" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/text_get"
android:text="MainActivity信息为:Hello"
android:textSize="20sp" />
<Button
android:id="@+id/btn_get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="得到碎片信息" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<FrameLayout
android:id="@+id/another_right_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></FrameLayout>
<FrameLayout
android:id="@+id/right_layout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></FrameLayout>
</LinearLayout>
</LinearLayout>
布局如图,左侧添加的LinearLayout,右侧分为两部分,每一部分都是一个FrameLayout,用来加载碎片。
然后我们编写碎片对应的XML文件和对应的类,代码如下:
- 第一个是right_fragment.xml和其对应的类
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:background="@color/red">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="this is right fragment"
android:textSize="20sp" />
</LinearLayout>
right_fragment.java文件:
package com.example.fragment_text;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class RightFragment extends Fragment {
String string;
View view;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view=inflater.inflate(R.layout.right_fragment,container,false);
return view;
}
//得到碎片TextView的内容
public String getString() {
TextView textView=view.findViewById(R.id.right_text);
return textView.getText().toString();
}
}
- 第二个是another_right_fragment.xml和其对应的类
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:background="@color/orange"
android:orientation="vertical">
<TextView
android:id="@+id/text_fragment_get"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="无"/>
<Button
android:id="@+id/btn_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="得到活动信息"
/>
<TextView
android:id="@+id/text_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment信息:Yeah"
android:textSize="20sp"/>
</LinearLayout>
anotherRightFragment.java文件:
package com.example.fragment_text;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.ButtonBarLayout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class AnotherRightFragment extends Fragment {
private View view;
private String string;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view=inflater.inflate(R.layout.another_right_fragment,container,false);
Button button=view.findViewById(R.id.btn_fragment);
final TextView textView=view.findViewById(R.id.text_fragment);
button.setOnClickListener(new View.OnClickListener() {
@Override
//得到活动内TextView的内容
public void onClick(View v) {
MainActivity mainActivity=(MainActivity) getActivity();
TextView textView1=view.findViewById(R.id.text_fragment_get);
textView1.setText(mainActivity.getString());
}
});
Button button1=view.findViewById(R.id.get_fragment_text);
button1.setOnClickListener(new View.OnClickListener() {
@Override
//得到另一个碎片TextView的内容
public void onClick(View v) {
MainActivity mainActivity=(MainActivity)getActivity();
TextView textView1=view.findViewById(R.id.another_fragment_text);
RightFragment rightFragment=new RightFragment();
rightFragment=(RightFragment) mainActivity.getSupportFragmentManager().findFragmentById(R.id.right_layout);
textView1.setText(rightFragment.getString());
}
});
return view;
}
public String getString() {
TextView textView=view.findViewById(R.id.text_fragment);
return textView.getText().toString();
}
}
在类中,我们继承了Fragment,其中要注意的是继承用 android.support.v4.app.Fragment包,然后重写onCreateView方法,在这个方法中通过LayoutInflater 的 inflate()方法将刚才定义的 left_fragment布局动态加载进来,对于该类中的控件的操作,一般都在此方法中使用,最后返回一个view。就类似活动有一个自己的xml文件和自己的java文件。
最后编写MainActivity文件,代码如下:
package com.example.fragment_text;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private String string;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.btn);
Button button1 = findViewById(R.id.btn_get);
TextView textView1 = findViewById(R.id.text);
string = textView1.getText().toString();
button.setOnClickListener(this);
button1.setOnClickListener(this);
}
//得到TextView内容的方法
public String getString() {
return string;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn:
AnotherRightFragment anotherRightFragment = new AnotherRightFragment();
repalceFragment(anotherRightFragment, R.id.another_right_layout);
repalceFragment(new RightFragment(), R.id.right_layout);
break;
//和碎片进行通信,得到碎片内的方法
case R.id.btn_get:
anotherRightFragment = (AnotherRightFragment) getSupportFragmentManager().findFragmentById(R.id.another_right_layout);
TextView textView = findViewById(R.id.text_get);
textView.setText(anotherRightFragment.getString());
break;
}
}
//动态加载碎片方法
private void repalceFragment(Fragment fragment, int layout) {
FragmentManager fragmentManager = getSupportFragmentManager();//获取FragmentManager
FragmentTransaction transaction = fragmentManager.beginTransaction();//开启一个事物
transaction.replace(layout, fragment);//向容器内添加或替换碎片,传入id和待添加的碎片实例
transaction.addToBackStack(null);//模拟返回栈
transaction.commit();//提交事务
}
}
可以看到,首先我们给左侧碎片中的按钮注册了一个点击事件,然后将动态添加碎片的 逻辑都放在了点击事件里进行。结合代码可以看出,动态添加碎片主要分为 5步。
- 创建待添加的碎片实例。
- 获取到 FragmentManager,在活动中可以直接调用 getFragmentManager()方法得到。
- 开启一个事务,通过调用 beginTransaction()方法开启。
- 向容器内加入碎片,一般使用 replace()方法实现,需要传入容器的 id和待添加的碎 片实例。
- 提交事务,调用 commit()方法来完成。
- 其中我们添加了一个返回栈的方法,因为通过点击按钮添加了一个碎片之后,这时按下 Back键程序就会直接退出。如果想按下 Back键可以回到上一个碎片,则需要addToBackStack方法,此时就碎片会像栈一样先进后出。
碎片与活动间的通信
1.为了方便碎片和活动之间进行通信,FragmentManager提供了一个类似于 findViewById()
的方法,专门用于从布局文件中获取碎片的实例,代码如下所示:
AnotherRightFragment anotherRightFragment = (AnotherRightFragment) getSupportFragmentManager().findFragmentById(R.id.another_right_layout);
TextView textView = findViewById(R.id.text_get);
textView.setText(anotherRightFragment.getString());
调用 FragmentManager的 findFragmentById()方法,可以在活动中得到相应碎片的实例, 然后就能轻松地调用碎片里的方法了。
2.在每个碎片中都可以通过调用 getActivity()方法来得到和当前碎片相关联 的活动实例,代码如下所示:
MainActivity mainActivity=(MainActivity) getActivity();
TextView textView1=view.findViewById(R.id.text_fragment_get);
textView1.setText(mainActivity.getString());
有了活动实例之后,在碎片中调用活动里的方法就变得轻而易举了。另外当碎片中需要 使用 Context对象时,也可以使用 getActivity()方法,因为获取到的活动本身就是一个 Context 对象了。
碎片与碎片通信
,首先在一个碎片中 可以得到与它相关联的活动,然后再通过这个活动去获取另外一个碎片的实例,这样也就实 现了不同碎片之间的通信功能
MainActivity mainActivity=(MainActivity)getActivity();
TextView textView1=view.findViewById(R.id.another_fragment_text);
RightFragment rightFragment=new RightFragment();
rightFragment=(RightFragment) mainActivity.getSupportFragmentManager().findFragmentById(R.id.right_layout);
textView1.setText(rightFragment.getString());
需要注意的是,进行通信时,获取实例是必须用(你需要得到的实例类)强制转换,不然会报错