ViewPager+Fragment原来这么简单

原创 2014年12月18日 16:59:16

我们在使用微信或是网易客户端的时候都会看到下面这样的效果,左右滑动切换页面,点击table栏也可以切换界面,以前看着感觉好高大上,今天用ViewPager和Fragment实现了一下,其实还是蛮好实现的

关键点:

1.viewPage的用法大家要掌握,主要就是设置适配器(.setAdapter()),设置监听函数(setOnCheckedChangeListener()),设置当前展示页面((setCurrentItem))

2.下面的table使用RadioGroup来实现,我们看效果,只能选中其中一个,这个正好符合RadioGroup的特点,用它来实现,非常简单

3.Fragment的用法大家应该了解,而且Fragment的跳转方法大家应该掌握(下面具体讲)

4.viewPager动的同时也要设置RadioGroup的选中按钮,同时RadioGroup点击事件也要出发ViewPager的滑动事件

明白了以上几点,就可以来看代码了:

首先,配置文件,在配置文件中我用到了style,dimen,shap,selector等一些知识点,大家有不清楚的可以留言,这个不是本博客的重点:

<?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.support.v4.view.ViewPager
        android:id="@+id/vpContainer"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:padding="@dimen/activity_horizontal_margin"/>
    
    <RadioGroup 
        android:id="@+id/rgTabBtns"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <RadioButton 
            android:id="@+id/rb_runingApp"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" 
            android:text="@string/tag_running_app"
            style="@style/MainTags"/>
        <RadioButton 
            android:id="@+id/rb_runingService"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/tag_running_service"
            style="@style/MainTags"/>
    </RadioGroup>

</LinearLayout>
ok,配置文件就是这么简单,但在具体使用Android那些小的属性的时候还是很繁琐的,最好动手实现一下

接下来是ViewPager的监听事件,注释应该很清楚了

	private OnPageChangeListener onPageChangeListener=new OnPageChangeListener() {
		
		@Override
		public void onPageSelected(int arg0) {
			// TODO Auto-generated method stub
			//viewPager的第arg0页处于当前屏幕的时候,将当前的arg0值赋值给记录Fragment的标签
			mCurrentFragment=arg0;
			//将下面tab的RadioGroup的第arg0个radioButton设为选中状态
			((RadioButton)rgTabButtons.getChildAt(arg0)).setChecked(true);
		}
		
		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void onPageScrollStateChanged(int arg0) {
			// TODO Auto-generated method stub
			
		}
	};
接下来是FragmentPagerAdapter的实现,google专门给我们提供了FragmentPagerAdapter,可见google对fragment下了很大的信心
	class KickerFragmentAdapter extends FragmentPagerAdapter{
		private Context mContext;
		
		public KickerFragmentAdapter(FragmentManager fm ,Context context) {
			super(fm);
			mContext=context;
		}

		@Override
		public Fragment getItem(int arg0) {
			// TODO Auto-generated method stub
			//根据fragment的包名得到对应的fragment
			return Fragment.instantiate(mContext, fragments[arg0]);
		}

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return fragments.length;
		}

	}

	@Override
	public void onJump() {
		// TODO Auto-generated method stub
		//Log.e("wj", ""+a);
		vpContainer.setCurrentItem(0);
		((RadioButton)rgTabButtons.getChildAt(0)).setChecked(true);
	}
这里主要页就是getItem方法了,它是用fragment的包名来指定对应的fragment。再然后就是RadioGroup的监听事件了
	private OnCheckedChangeListener onCheckedChangeListener=new OnCheckedChangeListener() {
		
		@Override
		public void onCheckedChanged(RadioGroup group, int checkedId) {
			//设置一个标签,用来记录当前所选的radioButton值
			int checkedItem=0;
			switch (checkedId) {
			case R.id.rb_runingApp:
				checkedItem=0;
				break;
			case R.id.rb_runingService:
				checkedItem=1;
				break;
			}
			//将ViewPager的第checkedItem个页面设为当前屏幕的展示页面
			vpContainer.setCurrentItem(checkedItem);
			//mCurrentFragment=checkedItem;
		}
	};
最后再把实例化以及设置监听代码都附上,省的有同学看不懂(0.0)
public class MainActivity extends FragmentActivity implements OnJumpListener{

	//记录当前Fragment
	private int mCurrentFragment;
	//fragment的类名
	private String[] fragments=new String[]{
		F_1.class.getName(),
		F_2.class.getName()
	};
	
	private ViewPager vpContainer;
	private RadioGroup rgTabButtons;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initComponents();
	}

	private void initComponents() {
		// TODO Auto-generated method stub
		//初始化控件
		vpContainer=(ViewPager) findViewById(R.id.vpContainer);
		rgTabButtons=(RadioGroup) findViewById(R.id.rgTabBtns);
		//创建viewPager 的适配器!Android给我们提供了FragmentPageAdapter
		KickerFragmentAdapter adapter=new KickerFragmentAdapter(getSupportFragmentManager(), this);
		//viewPager设置适配器,以及滑动viewPage监听事件
		vpContainer.setAdapter(adapter);
		vpContainer.setOnPageChangeListener(onPageChangeListener);
		//设置当前ViewPager展示的fragment
		vpContainer.setCurrentItem(mCurrentFragment);
		
		//RadioGroup设置监听事件
		rgTabButtons.setOnCheckedChangeListener(onCheckedChangeListener);
		//设置RadioGroup的第一个RadioButton为选中状态
		((RadioButton)rgTabButtons.getChildAt(0)).setChecked(true);
	}
ok,其实代码一点不难,重要的是我们要理清楚思路!哦,差点忘了,Fragment的跳转我们一般这么来实现:

1.在想要实现跳转的fragment设置一个接口,接口里定义一个方法(如果我们想带参数,可以在方法中定义参数)

2.然后我们在宿主Activity中实现这个接口,重写其方法,在此方法中完成fragment想要实现的跳转

3.这里为了防止我们的Activity忘了实现这个接口,在fragment重写了onAttach()方法,抛出了异常,如果不activity不实现此接口就会报错

最后再放一个fragment的类吧,要不有些同学总感觉少了点什么

public class F_2 extends Fragment {
	
	private Button button;
	
	public interface OnJumpListener{
		public void onJump();
	}
	
	private OnJumpListener listener;
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View contentView=inflater.inflate(R.layout.f_2, container,false);
		
		button=(Button) contentView.findViewById(R.id.btn);
		button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				listener.onJump();
			}
		});
		
		return contentView;
	}
	@Override
	public void onAttach(Activity activity) {
		// TODO Auto-generated method stub
		super.onAttach(activity);
		try {
			listener=(OnJumpListener)activity;
		} catch (ClassCastException e) {
			// TODO Auto-generated catch block
			throw new ClassCastException(activity.toString()  
	                + " must implement OnRunningAppRefreshListener");  
		}
	}
	
}


实现了上面的功能,心里别提有多爽了,但这你就满足了吗,如果我要实现下面的效果呢,我艹,为什么下面要定义图片呢,文字不是很好吗(兄弟这个不是我们程序猿说了算的啊,要怪就怪项目经理那个大xx)。那么这个效果如何实现呢,其实有了上面的例子,很简单,我们仿照上面的样子,将下面的table封装成一个自定义类,然后放两个类似RadioGroup的接口出来不就Ok了么



自定义MyTable类,

package com.wj.myview;

import com.wj.fragments.F_2.OnJumpListener;
import com.wj.fragmentviewpage.R;

import android.content.Context;
import android.net.VpnService;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MyTableView extends LinearLayout{

	private Context mContext;
	private LayoutInflater inflater;
	
	private int[] optionsBgNormal;
	private int[] optionsBgActive;
	
	private int OPTION_NUM=2;
	private LinearLayout[] optionContainer;
	private ImageView[] optionImageViews;
	private TextView[] optionTextViews;
	
	//设置点击事件的接口
	public interface MyOnTableClickListener{
		void onTableClick(int choice);
	}
	
	private MyOnTableClickListener mOnTableClickListener;
	//用来让Activity中的tableView设置监听事件
	public void setOnTableClickListener(MyOnTableClickListener myOnTableClickListener){
		mOnTableClickListener=myOnTableClickListener;
	}
	
	
	public MyTableView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		mContext=context;
		inflater=LayoutInflater.from(mContext);
	}
	//专门提供一个方法用来初始化tablview的按钮
	public void setDatas(int[] iconNormalIds ,int[] iconActiveIds){
		optionsBgNormal=iconNormalIds;
		optionsBgActive=iconActiveIds;
		
		initViews();
	}

	private void initViews() {
		View convertView=inflater.inflate(com.wj.fragmentviewpage.R.layout.myview_table, this);
		
		optionContainer=new LinearLayout[OPTION_NUM];
		optionImageViews=new ImageView[OPTION_NUM];
		optionTextViews=new TextView[OPTION_NUM];
		
		optionContainer[0]=(LinearLayout) convertView.findViewById(R.id.mContainer0Layout);
		optionContainer[1]=(LinearLayout) convertView.findViewById(R.id.mContainer1Layout);
		
		optionImageViews[0]=(ImageView) convertView.findViewById(R.id.mIcon0ImageView);
		optionImageViews[1]=(ImageView) convertView.findViewById(R.id.mIcon1ImageView);
		
		optionTextViews[0]=(TextView) convertView.findViewById(R.id.textview_home);
		optionTextViews[1]=(TextView) convertView.findViewById(R.id.textview_goods);
		
		optionContainer[0].setOnClickListener(mOnClickListener);
		optionContainer[1].setOnClickListener(mOnClickListener);
		
		
		for(int i=0;i<OPTION_NUM;i++){
			optionImageViews[i].setBackgroundResource(optionsBgActive[i]);
			optionTextViews[i].setTextColor(getResources().getColor(R.color.dimGray));
		}
	}
	//点击事件监听,其中调用了接口中的方法
	OnClickListener mOnClickListener=new OnClickListener() {
		@Override
		public void onClick(View v) {
			int choice=0;
			switch (v.getId()) {
			case R.id.mContainer0Layout:
				choice=0;
				break;
			case R.id.mContainer1Layout:
				choice=1;
				break;
			}
			
			handleClickEffect(choice);
			
			if(mOnTableClickListener!=null){
				mOnTableClickListener.onTableClick(choice);
				}
			}
		};
		//点击效果的实现
		public void handleClickEffect(int choice){
			for(int i=0;i<OPTION_NUM;i++){
				if(i==choice){
					optionImageViews[i].setBackgroundResource(optionsBgActive[i]);
					optionTextViews[i].setTextColor(getResources().getColor(R.color.orangered));
				}else{
					optionImageViews[i].setBackgroundResource(optionsBgNormal[i]);
					optionTextViews[i].setTextColor(getResources().getColor(R.color.dimGray));
				}
			}
		}
		//提供设置当前点击按钮的方法
		public void setCurItem(int choice){
			handleClickEffect(choice);
			if(mOnTableClickListener!=null){
				mOnTableClickListener.onTableClick(choice);
			}
		}
}
mytableView的页面也很简单
<?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" >
     <LinearLayout
        android:id="@+id/mContainer0Layout"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:layout_weight="1"
	    android:orientation="vertical"
	    android:gravity="center">
	    <ImageView
	        android:id="@+id/mIcon0ImageView" 
	        android:layout_width="@dimen/tabview_icon_width"
	        android:layout_height="@dimen/tabview_icon_height"
	        android:layout_marginTop="@dimen/tabview_icon_margin_top"/>
	    <TextView 
	        android:id="@+id/textview_home"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_marginTop="@dimen/tabview_text_margin_top"
	        android:gravity="center_horizontal"
	        android:text="@string/tabview_home"
	        android:textSize="@dimen/tag_textSize"/>
	</LinearLayout>
	<LinearLayout
	    android:id="@+id/mContainer1Layout"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:layout_weight="1"
	    android:orientation="vertical"
	    android:gravity="center">
	    <ImageView
	        android:id="@+id/mIcon1ImageView" 
	        android:layout_width="@dimen/tabview_icon_width"
	        android:layout_height="@dimen/tabview_icon_height"
	        android:layout_marginTop="@dimen/tabview_icon_margin_top"/>
	    <TextView 
	        android:id="@+id/textview_goods"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_marginTop="@dimen/tabview_text_margin_top"
	        android:gravity="center_horizontal"
	        android:text="@string/tabview_goods"
	       	android:textSize="@dimen/tag_textSize"/>
	</LinearLayout>

</LinearLayout>
最后就是Activity中的实现了,其实跟RadioGroup大同小异
public class OtherActivity extends FragmentActivity implements MyOnTableClickListener,OnJumpListener {
	
	//记录当前Fragment
	private int mCurrentFragment;
	//fragment的类名
	private String[] fragments=new String[]{
		F_1.class.getName(),
		F_2.class.getName()
		};
	private ViewPager vpContainer;
	//定义选中和未选中时的按钮状态
	private int[] tabviewNomalIcons={R.drawable.tabview_home ,R.drawable.tabview_goods };
	private int[] tabviewActiveIcons={R.drawable.tabview_home_activ ,R.drawable.tabview_goods_activ };
	
	private MyTableView mTableView;
	
	@Override
	protected void onCreate(Bundle arg0) {
		// TODO Auto-generated method stub
		super.onCreate(arg0);
		setContentView(R.layout.activity_other);
		initComponents();
	}
	private void initComponents() {
		// TODO Auto-generated method stub
		//初始化控件
		vpContainer=(ViewPager) findViewById(R.id.vpContainer);
		mTableView=(MyTableView) findViewById(R.id.mtv);
		//创建viewPager 的适配器!Android给我们提供了FragmentPageAdapter
		KickerFragmentAdapter adapter=new KickerFragmentAdapter(getSupportFragmentManager(), this);
		//viewPager设置适配器,以及滑动viewPage监听事件
		vpContainer.setAdapter(adapter);
		vpContainer.setOnPageChangeListener(onPageChangeListener);
		//设置当前ViewPager展示的fragment
		vpContainer.setCurrentItem(mCurrentFragment);
		
		//实现MyTableView的点击监听事件
		mTableView.setDatas(tabviewNomalIcons, tabviewActiveIcons);
		mTableView.setOnTableClickListener(this);
		//设置默认第一个按钮处于选中状态
		mTableView.setCurItem(0);
	}
	
	private OnPageChangeListener onPageChangeListener=new OnPageChangeListener() {
		
		@Override
		public void onPageSelected(int arg0) {
			// TODO Auto-generated method stub
			//viewPager的第arg0页处于当前屏幕的时候,将当前的arg0值赋值给记录Fragment的标签
			mCurrentFragment=arg0;
			//viewPager改变的时候对应的table按钮随之改变
			mTableView.setCurItem(arg0);
		}
		
		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
			// TODO Auto-generated method stub
			
		}
		
		@Override
		public void onPageScrollStateChanged(int arg0) {
			// TODO Auto-generated method stub
			
		}
	};
	
	@Override
	public void onTableClick(int choice) {
		// TODO Auto-generated method stub
		//tableView的点击监听事件,只要将viewPager设置成当前点击对应的页面就Ok
		vpContainer.setCurrentItem(choice);
	}
	
	class KickerFragmentAdapter extends FragmentPagerAdapter{
		private Context mContext;
		
		public KickerFragmentAdapter(FragmentManager fm ,Context context) {
			super(fm);
			mContext=context;
		}

		@Override
		public Fragment getItem(int arg0) {
			// TODO Auto-generated method stub
			//根据fragment的包名得到对应的fragment
			return Fragment.instantiate(mContext, fragments[arg0]);
		}

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return fragments.length;
		}

	}

	@Override
	public void onJump() {
		// TODO Auto-generated method stub
//		vpContainer.setCurrentItem(0);
		//用于fragment之间跳转的方法
		mTableView.setCurItem(0);
	}
}


   源码下载

版权声明:欢迎大家留言讨论

ViewPager 详解(五)-----使用Fragment实现ViewPager滑动

前言:前几篇yy

ViewPager+Fragment避免重复createview

ViewPager+Fragment避免重复createview 每次使用ViewPager+Fragment来作为app的框架的时候都要格外小心,因为他们的生命周期有点奇怪,并没有Activit...

使用ViewPager和Fragment实现底部导航滑动重构版

感谢刘大神写的项目,参考自点击这里,本文对其进行了简单重构,写下思路,供自己以后思考。自定义view设置每个页面的子itemlayout_tab_item.xml,每个item由一个ImageView...

Android ViewPager+Fragment 仿 Google Play

最近终于从繁忙的网络爬虫项目中解脱出来,回到久违的Android开发岗位,有时间研究Android 4.0的一些新特性,例如Fragment和ViewPager,参考了一些他人的代码,做出来了Goog...
  • FX_SKY
  • FX_SKY
  • 2013年05月29日 18:17
  • 37791

ViewPager 从入门到带你撸个启动页之Fragment+ViewPager(二)

上一篇我们分享了ViewPager的基本用法后,相信大家对ViewPager的使用已经有比较清晰的认识了,这篇我们准备来使用官方推荐的Fragment+ViewPager组合来实现上一篇的效果。Fra...

使用Fragment填充ViewPager

今天我们实现的是使用Fragment来填充ViewPager,首先说一下,很重要,我们要使用Fragment 来填充ViewPager布局的话。我们所有的类所继承的类的包都是在v4包下的,注意咯!这...

ViewPager和Fragment的组合使用

支持手指滑动切换页面,也支持点击导航按钮切换页面。 页面布局文件: [html] view plaincopy RelativeLayout xmlns:android="h...

使用ViewPager加载Fragment

ViewPager加载Fragment

如何更新及替换ViewPager中的Fragment

在Android应用中遇到的问题? 在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fr...

关于在ViewPager中添加Fragment的问题

我们在什么情况下能使用到这个呢? 一般的情况,ViewPager只需要简单的实现PagerAdapter即可。可是当你遇到这种情况,ViewPager中的View本身有着大量的数据处理工作,要调很多接...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ViewPager+Fragment原来这么简单
举报原因:
原因补充:

(最多只允许输入30个字)