说到现在app的Tab选项卡,随处可见,微信、QQ音乐数不胜数,因此了解并掌握实现原理显得尤为重要。原理并不是特别的复杂,初学android一定要多动手,多敲代码。今天就说说App界面Tab选项卡之ViewPager。
先说说ViewPager,附加于android-support-v4.jar中,用于实现view之间的相互切换,一般新建时便会自动生成,在xml中应用须输入完整路径,例如:
<android.support.v4.view.ViewPager
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
ViewPager可以设置专门的PagerAdapter,用于填充用于滑动的view集合,还可以配合OnPageChangeListener一起使用,监听切换视图的状态。更具体详细信息自行google,好了,开始今天的任务。
我们的目标是实现类似微信主界面那样的Tab选项卡,效果图如下图:
有了目标,那么就开始做准备工作了,很明显,我们需要一个title_bar:
<?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="45dp" android:background="@drawable/bar_bg" android:orientation="vertical">
<TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="微信" android:textColor="#fff" android:textSize="20sp" />
</LinearLayout>
还有一个bottom_bar,用于ViewPager的Indicator:
<?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="55dp" android:background="@drawable/bar_bg" android:orientation="horizontal">
<LinearLayout android:id="@+id/tab_0" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">
<ImageView android:id="@+id/img_0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_weixin_pressed" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="微信" android:textColor="#fff" />
</LinearLayout>
<LinearLayout android:id="@+id/tab_1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">
<ImageView android:id="@+id/img_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_find_frd_normal" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="朋友" android:textColor="#fff" />
</LinearLayout>
<LinearLayout android:id="@+id/tab_2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">
<ImageView android:id="@+id/img_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_address_normal" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="通讯录" android:textColor="#fff" />
</LinearLayout>
<LinearLayout android:id="@+id/tab_3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:orientation="vertical">
<ImageView android:id="@+id/img_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/tab_settings_normal" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置" android:textColor="#fff" />
</LinearLayout>
</LinearLayout>
还有四个内容页,我就不贴了,最后是主界面:
<?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">
<include layout="@layout/title_bar" />
<android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" />
<include layout="@layout/bottom_bar" />
</LinearLayout>
唯一的技巧可能就是用了include,开始编写MainActivity代码段:
package com.cjt_pc.viewpager;
import android.app.Activity;
import android.media.Image;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.ArrayList;
import java.util.List;
/** * Created by cjt-pc on 2015/8/20. * Email:879309896@qq.com */
public class MainActivity extends Activity implements View.OnClickListener {
private ViewPager viewPager;
// 填充ViewPager的页面集合
private List<View> views = new ArrayList<>();
// ViewPager指示器布局
private LinearLayout llIndicator0, llIndicator1, llIndicator2, llIndicator3;
private ImageView ivImg0, ivImg1, ivImg2, ivImg3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initWidget();
initViewPager();
}
private void initViewPager() {
initViews();
viewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return views.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = views.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
}
});
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
// 只有当前select项发生改变才会调用该方法,初始化ViewPager时默认选中第一项,但不会触发该方法
@Override
public void onPageSelected(int position) {
resetIndicator();
switch (position) {
case 0:
ivImg0.setImageResource(R.mipmap.tab_weixin_pressed);
break;
case 1:
ivImg1.setImageResource(R.mipmap.tab_find_frd_pressed);
break;
case 2:
ivImg2.setImageResource(R.mipmap.tab_address_pressed);
break;
case 3:
ivImg3.setImageResource(R.mipmap.tab_settings_pressed);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void initWidget() {
viewPager = (ViewPager) findViewById(R.id.view_pager);
llIndicator0 = (LinearLayout) findViewById(R.id.tab_0);
llIndicator0.setOnClickListener(this);
llIndicator1 = (LinearLayout) findViewById(R.id.tab_1);
llIndicator1.setOnClickListener(this);
llIndicator2 = (LinearLayout) findViewById(R.id.tab_2);
llIndicator2.setOnClickListener(this);
llIndicator3 = (LinearLayout) findViewById(R.id.tab_3);
llIndicator3.setOnClickListener(this);
ivImg0 = (ImageView) findViewById(R.id.img_0);
ivImg1 = (ImageView) findViewById(R.id.img_1);
ivImg2 = (ImageView) findViewById(R.id.img_2);
ivImg3 = (ImageView) findViewById(R.id.img_3);
}
private void initViews() {
View view0 = getLayoutInflater().inflate(R.layout.content_0, null);
View view1 = getLayoutInflater().inflate(R.layout.content_1, null);
View view2 = getLayoutInflater().inflate(R.layout.content_2, null);
View view3 = getLayoutInflater().inflate(R.layout.content_3, null);
views.add(view0);
views.add(view1);
views.add(view2);
views.add(view3);
}
@Override
public void onClick(View view) {
// 若点击的indicator项与viewpager的项相等,则不采取任何操作
int position = viewPager.getCurrentItem();
switch (view.getId()) {
case R.id.tab_0:
if (position != 0) {
resetIndicator();
viewPager.setCurrentItem(0);
}
break;
case R.id.tab_1:
if (position != 1) {
resetIndicator();
viewPager.setCurrentItem(1);
}
break;
case R.id.tab_2:
if (position != 2) {
resetIndicator();
viewPager.setCurrentItem(2);
}
break;
case R.id.tab_3:
if (position != 3) {
resetIndicator();
viewPager.setCurrentItem(3);
}
break;
}
}
private void resetIndicator() {
ivImg0.setImageResource(R.mipmap.tab_weixin_normal);
ivImg1.setImageResource(R.mipmap.tab_find_frd_normal);
ivImg2.setImageResource(R.mipmap.tab_address_normal);
ivImg3.setImageResource(R.mipmap.tab_settings_normal);
}
}
几个关键位置说一下,onPageChangeListener的三个抽象方法,各有千秋:
- onPageScrolled:视图滚动式触发
- onPageSelected:手指抬起viewPager.getCurrentItem()发生改变时触发,初始化时默认选中0项,但并不会触发该方法
- onPageScrollStateChanged:viewPager滑动状态改变时触发,有三个参数,SCROLL_STATE_DRAGGING;SCROLL_STATE_IDLE;SCROLL_STATE_SETTLING;分别是手指拖拽、视图停止滚动、手指抬起视图开始滑动到完全显示某一页面的过程。
所以会在bottom.xml为bottom首项img设置初始值为pressed,因为页面index不发生改变onPageSelected不会触发,所以在onClick中会加入判断。
大概就是这样了,项目源码地址:http://download.csdn.net/detail/qq_15002323/9033803