我们在使用微信或是网易客户端的时候都会看到下面这样的效果,左右滑动切换页面,点击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);
}
}