Android(安卓)Studio开发学习(十三)——Fragment
一、前提
Fragment作为Android最基本,最重要的基础概念之一,在开发中经常会和他打交道。Fragment有自己的生命周期,依赖于Activity,可以与Activity的相互获取(Fragment通过getActivity()获取Activity;Activity通过FragmentManger的findFragmentById()或findFragmentByTag()获取Fragment),与Activity的多对多关系
二、目标
Fragment
三、内容
1、Fragment在Activity中的基本运行
先在activity_main中添加如下布局文件,一个按钮和一个布局管理器
<?xml version="1.0" encoding="utf-8"?>
分别建立两个新的java文件,且其中的代码相同,这里展示一个
在xml文件中添加一个TextView
<?xml version="1.0" encoding="utf-8"?>
在java文件中添加
package com.example.sunny.fragment;import android.app.Fragment;import android.os.Bundle;import android.support.annotation.Nullable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by Sunny on 2020/4/24. */public class BFragment extends Fragment { private TextView textView; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view=inflater.inflate(R.layout.fragmentb,container,false); return view; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); textView= (TextView) view.findViewById(R.id.tv); }}
在此处我们可以看到java文件继承Fragment
且常用的两种方法是:
onCreateView()方法,该方法返回视图文件,相当于Activity中onCreate方法中setContentView一样
onViewCreated()方法,该方法当view创建完成之后的回调方法
说白了就是一个用于创造,一个用于运用
在onCreateView()中首先还是找到为它写的布局文件,返回视图文件
在onViewCreated()中找到其视图文件中的各类控件进行使用
在MainActivity中添加
package com.example.sunny.fragment;import android.content.Intent;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 { private AFragment aFragment; private BFragment bFragment; private Button button; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button= (Button) findViewById(R.id.btn); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (bFragment == null) { bFragment = new BFragment(); } //返回FragmentManager,用于与与此活动关联的片段进行交互;;在与这个片段管理器关联的片段上启动一系列编辑操作 getFragmentManager().beginTransaction().replace(R.id.fl, bFragment).commitAllowingStateLoss(); } }); //实例化AFragment //aFragment=AFragment.newInstance("hello"); aFragment=new AFragment(); //把AFragment添加到Activity中,记得调用commit getFragmentManager().beginTransaction().add(R.id.fl,aFragment).commitAllowingStateLoss(); }
逻辑就是:首先实例化一个Fragment,将Fragment添加到Activity中,通过按钮点击跳转至另一个Fragment
getFragmentManager().beginTransaction()是固定操作,关键在于你是想要替换还是添加,都是将fragment的实例传给之前布局的LinearLayout中,最后提交,一般使用commitAllowingStateLoss()方法进行提交因为commmit()方法有时会报错
2、向Fragment传递参数
在AFragment中添加一个静态方法,在该方法中进行实例化并且返回fragment
setArguments()方法:为这个片段提供构造参数。这只能在片段被连接到它的活动之前调用;也就是说,您应该在构建片段之后立即调用它。这里提供的参数将在片段销毁和创建之间保留。
public static AFragment newInstance(String title){ AFragment fragment=new AFragment(); Bundle bundle=new Bundle(); bundle.putString("title",title); fragment.setArguments(bundle); return fragment; }
在onViewCreated()方法中添加,判断之前创建的是否存在,若存在则可赋值
if(getArguments()!=null){ textView.setText(getArguments().getString("title")); }
最后在MainActivity中将之前实例化的语句改为
aFragment=AFragment.newInstance("hello");
3、Fragment回退栈
首先要对代码进行改动,去掉activity_main中的按钮,将它放置在AFragment的布局文件中,并且在添加一个按钮
<?xml version="1.0" encoding="utf-8"?>
在MainActivity中删除Button的点击事件,添加一个标记
package com.example.sunny.fragment;import android.content.Intent;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 { private AFragment aFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //实例化AFragment aFragment=AFragment.newInstance("hello"); //把AFragment添加到Activity中,记得调用commit getFragmentManager().beginTransaction().add(R.id.fl,aFragment,"a").commitAllowingStateLoss(); }}
注意:多了的那个"a"表示一个标记,可使用它来找寻相应的片段
在AFragment的java文件中的onViewCreated()中添加
button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (bFragment == null) { bFragment = new BFragment(); } Fragment fragment=getFragmentManager().findFragmentByTag("a"); if (fragment!=null){ getFragmentManager().beginTransaction().hide(fragment).add(R.id.fl, bFragment).addToBackStack(null).commitAllowingStateLoss(); }else{ getFragmentManager().beginTransaction().replace(R.id.fl, bFragment).addToBackStack(null).commitAllowingStateLoss(); } } }); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { textView.setText("new text"); } });
第一个按钮的作用是点击后调到下一个Fragment中,首先判断是否存在bFragment,若不存在则实例化一个,若存在,则先找是否发现标记a,若标记a的片段存在,则将它隐藏后添加新的Fragment,若不存在,则直接进行替换
addToBackStack(null)是将此事务添加到后堆栈。这意味着事务将在提交后被记住,并将在稍后弹出堆栈时反转其操作。他其中的参数是一个String name表示此回堆栈状态的可选名称,或null;一般写null;意思也就是说,添加这个方法后,你使用返回键后就会返回你的上一步操作,否则会直接回到你的首次操作,比如你有一个主页面,点击按钮后疯狂跳转,如果没有添加此方法,则点击返回键直接返回主页面,中间所有的跳转页面都不会再显示
hide()表示隐藏现有的片段。这只与那些视图已被添加到容器中的片段相关,因为这将导致视图被隐藏。这样你即使点击修改文字后,再进入BFragment后,返回看到的还是修改后的文字否则。你不管怎样更改文字内容,更换Fragment后返回看到的永远都是最初的文字,如下图
第二个按钮的作用是点击后文字改变,整个的效果
4、二者之间的通信
Fragment发送一个消息给Activity,让他去执行,利用回调接口的方法
先在AFragment的xml文件中在添加一个按钮
在AFragment的中写一个接口
private IOnMessageClick listener; public interface IOnMessageClick{ void onClick(String text); }
在MainActivity中实现这个接口,并且重写方法
package com.example.sunny.fragment;import android.content.Intent;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 AFragment.IOnMessageClick{ private AFragment aFragment; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView= (TextView) findViewById(R.id.title); //实例化AFragment aFragment=AFragment.newInstance("hello"); //aFragment=new AFragment(); //把AFragment添加到Activity中,记得调用commit getFragmentManager().beginTransaction().add(R.id.fl,aFragment,"a").commitAllowingStateLoss(); } @Override public void onClick(String text) { textView.setText(text); }}
在AFragment中,当Fragment依附于Activity时有一个方法,是onAttach(),表示当片段首次附加到其上下文时调用。
@Override public void onAttach(Context context) { super.onAttach(context); try{ listener= (IOnMessageClick) context; }catch(ClassCastException e){ e.printStackTrace(); } }
最后在新的按钮的点击事件中添加代码
listener.onClick("succeed");
四、总结
Fragment相对来说功能强大,与Activity相辅相成,很重要的一个知识点,也比较复杂
更多相关文章
- Android的onCreateOptionsMenu()创建菜单Menu详解
- Android实现点击事件的4种方式
- Unity3D游戏引擎实现在Android中打开WebView的实例
- Android学习路线[转]
- Android(安卓)Service
- Android应用程序获取ROOT权限的方法
- 让editView、AutoCompleteTextView开始捕获的焦点
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用