Fragment 和 ViewPager 基础
来源:互联网 发布:erp软件的前景 编辑:程序博客网 时间:2024/06/06 00:37
Fragment
Fragment 可以有自己独立的事件处理和生命周期 , fragment最初是为了大屏幕显示而设计, 有了fragment后手机和平板兼容就容易了, 比如平板上 Activity A 包含
FragmentA 和 FragmentB , 手机上就可以ActivityA 包含FragmentA ; ActivityB包含FragmentB ; 就不用重新在手机上大改布局文件, 只需要小改… fragment 可以包含到多个Activity中
使用fragment需要先定义一个类, 继承Fragment 并实现其onCreateView()方法 , Fragment第一次绘制其用户界面的时候,系统会调用该方法, 为了绘制fragment的UI该方法必须返回一个View, 如果不显示UI, 返回null即可
静态和动态加载
Fragment静态加载: 就是在layout的xml文件中有定义 标签
在Activity的layout文件中声明Fragment , fragment的name属性, 指定了layout实例化的Fragment类
必须有标示, id属性唯一id 或 tag属性唯一字符串
Fragment动态加载: Activity的layout布局文件中没有定义fragment控件, 而是在Activity中用代码加载
但无论是静态还是动态 , 都需要有自定义的fragment类和这个fragment对应的layout文件
并且这个fragment类里面需要重写onCreateView方法, 返回view , 一般是把layout转换为view返回
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment1, container); TextView tv = (TextView) view.findViewById(R.id.id_fragment1_tv); tv.setText("fragment 1 text"); Button btn = (Button) view.findViewById(R.id.id_fragment1_btn); btn.setText("btnOfFragment1"); return view; }
有了fragment类后, 动态加载需要fragment事务来加载到Activity
对fragment进行添加移除替换和其他动作, 提交给Activity的每一套变化称为事务
另外, 动态加载fragment最终还是把fragment加载到某个指定ID的layout
//动态加载fragment到ID为id_fram的LinearLayout中 Fragment fragment = new MyFragment2(); FragmentManager manager = getFragmentManager(); FragmentTransaction beginTransaction = manager.beginTransaction();//开启事务 beginTransaction.add(R.id.id_frame, fragment); //把fragment加载到指定ID的layout中 beginTransaction.addToBackStack(null);//fragment添加到返回栈 beginTransaction.commit();
每个事务都是一套变化 , 包括add() remove() replace() 然后提交给Activity, 必须调用commit() 方法
如果允许用户通过按下back返回到前一个fragment状态, 调用commit之前可以加入addToBackStack()方法
Fragment和Activity通信
1 fragment可以调用getActivity方法获取它所在的Activity
2 Activity可以调用FragmentManager的findFragmentById() 或findFragmentByTag()方法获取Fragment
Activity –> Fragment :
在Activity中创建Bundle数据包, 并调用Fragment的setArguments(Bundle bundle) 方法
Fragment –> Activity :
需要在
Fragment中定义一个内部回调接口, 再让包含该Fragment的Activity实现该回调接口. 这样在Fragment类中可以调用该回调方法将数据传递给Activity
Activity 传值给 Fragment :
//Activity端 @Override public void onClick(View v) { String data = tv_data.getText().toString(); //Activity中准备bundle数据 MyFragment4 myFragment4 = new MyFragment4(); Bundle bundle = new Bundle(); bundle.putString("data", data); //加载fragment前, 调用fragment对象的setArguments方法传递数据 myFragment4.setArguments(bundle); //和往常一样动态加载fragment到某个控件 FragmentManager manager = getFragmentManager(); FragmentTransaction beginTransaction = manager.beginTransaction(); beginTransaction.replace(R.id.id_activity4_layout,myFragment4); beginTransaction.addToBackStack(null); beginTransaction.commit(); Toast.makeText(Activity4.this, "Activity 发送数据给Fragment4:" + data, Toast.LENGTH_SHORT).show(); } });
//Fragment类中onCreateView方法中获取数据
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // inflater将布局文件转换为view View view = inflater.inflate(R.layout.fragment4, container, false); ... .... //获取Activity传递的数据; Bundle bundle = getArguments(); String txt = bundle.get("data").toString() ; Toast.makeText(getActivity(), "fragment 接收到数据:"+txt, Toast.LENGTH_SHORT).show(); return view; }
Fragment传值给Activity
fragment中定义接口, 然后activity实现接口方法,
fragment中onAttach 重写的时候, 把activity转换为接口实现对象,
fragment中在合适的地方调用activity强转接口对象中的方法 , 并传值, 于是实现fragment传递数据给activity
Fragment 类中:
public class MyFragment4 extends Fragment {//定义接口 public interface MyListener { public void thankyou (String str); } //定义接口对象 MyListener mListener; ...//复写onAttach方法时将实现了接口方法的activity强转并赋值给接口对象 @Override public void onAttach(Activity activity) { mListener = (MyListener) activity; super.onAttach(activity); }//在需要调用接口方法, 传值的时候调用接口方法 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub View view = inflater.inflate(R.layout.fragment4, container, false); ... Bundle bundle = getArguments(); String txt = bundle.get("data").toString() ; Toast.makeText(getActivity(), "fragment 接收到数据:"+txt, Toast.LENGTH_SHORT).show();//比如收到数据后, 返回一条确认字符串 mListener.thankyou(code); return view; }
//Activity中:
public class Activity4 extends Activity implements MyListener{ ... ... ... //通过实现接口方法, 让fragment调用接口方法来实现fragment向Activity传值 @Override public void thankyou(String str) { Toast.makeText(Activity4.this, "Activity 接收到数据" + str, Toast.LENGTH_SHORT).show(); }}
activity传值给静态加载的fragment
Activity 的layout文件中有fragment字段, 静态加载MyFragment这个类的话
Fragment类中:
我们在MyFragment类中, 对需要传值的字段设置好getter , setter
public class MyFragment1 extends Fragment { private String testField; public String getTestField() { return testField; } public void setTestField(String testField) { this.testField = testField; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment1, container); TextView tv = (TextView) view.findViewById(R.id.id_fragment1_tv); tv.setText("fragment 1 text 静态加载"); Button btn = (Button) view.findViewById(R.id.id_fragment1_btn); btn.setText("btnOfFragment1"); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String data = getTestField(); Toast.makeText(getActivity(), "testField 现在的值为:" + data, Toast.LENGTH_SHORT).show(); } }); return view; } }
Activity中:
FragmentManager fragmentManager = getFragmentManager(); Fragment fragment = fragmentManager.findFragmentById(R.id.id_activity4_staticFrag); MyFragment1 myfragment1 = (MyFragment1) fragment; myfragment1.setTestField("测试传值给fragment");
Fragment类中 调用 getXxx() 方法即可得到Activity传递过来的数据
ViewPager
类: android.support.v4.view.ViewPager
加载显示的页卡, 页卡可以使view对象也可以使fragment对象
将layout布局文件转换为view对象的方法:
1 LayoutInflater
LayoutInflater lf = getLayoutInflater().from(this);
lf.inflate(resource,root);
2 View.inflate
View.inflate(context,resource,root);
配置Adapter
数据源可以使view也可以使fragment
1. PagerAdapter 数据源List
2. FragmentPagerAdapter 数据源 List
3. FragmentStatePagerAdapter 数据源 List
view 作为页卡 , 最简单的viewPager
//main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <android.support.v4.view.ViewPager android:id="@+id/id_pager" android:layout_width="wrap_content" android:layout_height="wrap_content" > </android.support.v4.view.ViewPager> </RelativeLayout>
Activity
//MainActivity.java public class MainActivity extends Activity { private List <View> viewList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); viewList = new ArrayList<View>(); /*** - view 对象作为数据源 */ View view1 = View.inflate(this, R.layout.view1, null); View view2 = View.inflate(this, R.layout.view2, null); View view3 = View.inflate(this, R.layout.view3, null); View view4 = View.inflate(this, R.layout.view4, null); viewList.add(view1); viewList.add(view2); viewList.add(view3); viewList.add(view4); //创建pager对象 ViewPager pager = (ViewPager) findViewById(R.id.id_pager); //加载适配器 MyPagerAdapter adapter = new MyPagerAdapter(viewList); pager.setAdapter(adapter); } }
//MyPagerAdapter
package com.example.imooc_viewpager; import java.util.List; import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; public class MyPagerAdapter extends PagerAdapter { List<View> mViewList ; public MyPagerAdapter(List<View> viewList) { mViewList = viewList; } /** - 返回页卡数量 */ @Override public int getCount() { // TODO Auto-generated method stub return mViewList.size(); } /*** - 判断view 是否来自对象 */ @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } /** - 实例化一个页卡 , viewpager一般是前, 后, 当前页卡, 一共3个页卡为单位的去操作 */ @Override public Object instantiateItem(ViewGroup container, int position) { // return super.instantiateItem(container, position); container.addView(mViewList.get(position)); return mViewList.get(position); } /*** - 销毁一个页卡 , 需要从viewGroup中移除一个view */ @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mViewList.get(position)); } }
加入页卡标题
1 XML文件中 , 加入PagerTabStrip 控件
<android.support.v4.view.ViewPager android:id="@+id/id_pager" android:layout_width="wrap_content" android:layout_height="wrap_content" > <android.support.v4.view.PagerTabStrip android:id="@+id/id_pager_tabStrip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" > //设置tabStrip在顶端显示 </android.support.v4.view.PagerTabStrip> </android.support.v4.view.ViewPager>
2 Activity中准备标题数据
private List <String> titleList; titleList = new ArrayList<String> (); titleList.add("第一页"); titleList.add("第二页"); titleList.add("第三页"); titleList.add("第四页");
3 自定义的MyPagerAdapter 类中实现getPageTitle 方法
//构造函数中传递titleList List<View> mViewList ; List<String> mTitleList; public MyPagerAdapter(List<View> viewList , List<String> titleList) { mViewList = viewList; mTitleList = titleList; }...... /** * 设置页卡标题 */ @Override public CharSequence getPageTitle(int position) { return mTitleList.get(position); }
4 设置属性
//为tabStrip 设置属性 tabStrip = (PagerTabStrip) findViewById(R.id.id_pager_tabStrip); tabStrip.setBackgroundColor(Color.YELLOW); //背景色 tabStrip.setTextColor(Color.RED); //文字颜色 tabStrip.setDrawFullUnderline(false); //去掉长的下划线 tabStrip.setTabIndicatorColor(Color.GREEN); //设置当前单项粗点的线的颜色
类似PagerTabStrip的还有PagerTitleStrip
<android.support.v4.view.PagerTitleStrip android:id="@+id/id_pager_titleStrip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom" > </android.support.v4.view.PagerTitleStrip>
使用Fragment作为Pager数据源
1 XML文件中 , 加入PagerTabStrip 控件
<android.support.v4.view.ViewPager android:id="@+id/id_pager" android:layout_width="wrap_content" android:layout_height="wrap_content" > <android.support.v4.view.PagerTabStrip android:id="@+id/id_pager_tabStrip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" > //设置tabStrip在顶端显示 </android.support.v4.view.PagerTabStrip> </android.support.v4.view.ViewPager>
2 创建Fragment类 , 注意使用的包 android.support.v4.app.Fragment; 兼容3.0以下版本
public class Fragment1 extends Fragment { @Override @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.view1, container, false); }}
定义4个这样的fragment分别加载4个不同的layout文件
3 自定义FragmentPagerAdapter类
import java.util.List;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;/*** * FragmentPagerAdapter 和 PagerAdapter加载的时候不同的是, * FragmentPagerAdapter 会一次把所有的fragment都加载进来, 而不是三个三个地加载 * @author hendry-code * */public class MyFragmentPagerAdapter extends FragmentPagerAdapter { private List<Fragment> mFragList; private List<String> mTitleList; public MyFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragList, List<String> titleList) { super(fm); mFragList = fragList; mTitleList = titleList; } @Override public Fragment getItem(int arg0) { // TODO Auto-generated method stub return mFragList.get(arg0); } @Override public int getCount() { // TODO Auto-generated method stub return mFragList.size(); } @Override public CharSequence getPageTitle(int position) { return mTitleList.get(position); }}
4 修改Activity文件, 使用fragmentAdapter
private List<Fragment> fragList; ... /** * Fragment 作为数据源 */ fragList = new ArrayList<Fragment>(); fragList.add(new Fragment1()); fragList.add(new Fragment2()); fragList.add(new Fragment3()); fragList.add(new Fragment4()); titleList = new ArrayList<String> (); titleList.add("第一页"); titleList.add("第二页"); titleList.add("第三页"); titleList.add("第四页"); //创建pager对象 pager = (ViewPager) findViewById(R.id.id_pager); //为tabStrip 设置属性 tabStrip = (PagerTabStrip) findViewById(R.id.id_pager_tabStrip); tabStrip.setBackgroundColor(Color.YELLOW); tabStrip.setTextColor(Color.RED); tabStrip.setDrawFullUnderline(false); //去掉长的下划线 tabStrip.setTabIndicatorColor(Color.GREEN); //设置当前单项粗点的线的颜色 MyFragmentPagerAdapter fragmentAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager(), fragList, titleList); pager.setAdapter(fragmentAdapter);
由于使用Fragment 是v4兼容包的Fragment, 所以 , FragmentPagerAdapter 的构造函数中需要一个fragmentManager 不能通过 getFragmentManager()来获得, 我们需要getSupportFragmentManager() ; 为了使用这个兼容包, 我们还需要把Activity改为继承自FragmentActivity.
使用FragmentStatePagerAdapter
FragmentPagerAdapter 是一次性加载所有的页卡, 没有动态添加销毁的功能 , 验证方法 , 在第四个fragment 销毁的时候打印LOG, 然后测试切换, 发现LOG没有打印
public class Fragment4 extends Fragment { @Override @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.view4, container, false); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.i("main","Fragment4 destoryed...."); }}
所以如果页卡很多的话FragmentPagerAdapter就不适合了, 我们需要另外一个有动态添加销毁功能的 FragmentStatePagerAdapter
把adapter的定义头部改一下, 并复写创建和销毁方法 , 但这两个方法不用去改什么, 原样就可以了
public class MyFragmentPagerAdapter2 extends FragmentStatePagerAdapter { ... ... @Override public Object instantiateItem(ViewGroup arg0, int arg1) { // TODO Auto-generated method stub return super.instantiateItem(arg0, arg1); } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub super.destroyItem(container, position, object); }...}Activity文件中: MyFragmentPagerAdapter2 fragmentAdapter2 = new MyFragmentPagerAdapter2(getSupportFragmentManager(), fragList, titleList); pager.setAdapter(fragmentAdapter2);
然后再模拟器上测试, 就发现从第三页切换到第二页的时候, 第四页的销毁LOG就被打印出来了, 说明FragmentStatePagerAdapter适配器是会动态维护创建销毁的
ViewPager 监听器 OnPageChangeListener
1 类定义的头文件 public class MainActivity extends FragmentActivity implements OnPageChangeListener {
2 完成接口方法, 主要是onPageSelected
@Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageSelected(int arg0) { // TODO Auto-generated method stub Toast.makeText(this, "当前是第" + (arg0 + 1) + "页面",Toast.LENGTH_SHORT).show(); }
3 OnCreate方法中 绑定Listener , pager.setOnPageChangeListener(this);
因为Fragment有完整的生命周期, 更好控制, 一般使用fragment + viewPager组合比较多…..
- Fragment 和 ViewPager 基础
- ViewPager+Fragment基础
- Fragment嵌套Fragment和Viewpager
- Fragment嵌套Fragment和Viewpager
- 关于ViewPager和Fragment
- ViewPager和Fragment
- ViewPager和Fragment简介
- ViewPager和Fragment
- fragment和viewpager
- Viewpager和Fragment
- android viewpager和fragment
- ViewPager和Fragment
- 0906Android基础ViewPager+Fragment
- android基础---ViewPager与fragment
- ViewPager和ViewPager+Fragment简单使用
- TabActivity 、fragemnt+fragment 和 Fragment+Viewpager 优缺点
- ViewPager和fragment的使用
- TabHost fragment 和 Viewpager 总结
- 【转】Android 多渠道打包:使用Gradle和Android Studio
- Windows平台下Makefile学习笔记(一)
- editplus快捷键大全
- Unable to find the wrapper "https"错误的解决办法
- Oracle 批量insert报错处理
- Fragment 和 ViewPager 基础
- new与malloc的区别
- 【CSS3】nth-of-type(n)选择器
- swipebacklayout 问题
- 从100PV到1亿级PV网站架构演变
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- MVVM结合ReactiveCocoa在项目实践中的理解和总结的一些经验
- 网络爬虫-有道翻译
- 打开虚拟机时报硬盘UUID 已经存在的解决办法