给公司做项目时间当时因为比较赶,首页使用了listview+Viewpager实现。当时代码都写到了一个类中,导致每次看首页都有种疯了的感觉,最近没事对首页进行了重构,将Viewpager单独抽取,listview改为新控件RecyclerView。虽然比较简单,网上也有很多实现好的开源项目,但是做为自己学习还是动手做了,然后记录下来吧。这篇我们先来看ViewPager的实现吧。
下面还是先来看个效果图吧:
呀,录制的貌似有点卡了,好吧将就看下吧。
首先是布局,也很简单是LinearLayout包了个RelativeLayout,然后RelativeLayout中有一个ViewPager和一个LinearLayout(用于底部的指示点)。看下吧(最外层的LinearLayout没有给出来)
<RelativeLayout
android:id="@+id/rl_head"
android:layout_width="match_parent"
android:layout_height="135dp">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="135dp"/>
<LinearLayout
android:id="@+id/index_point"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/transparent"
android:gravity="center"
android:orientation="horizontal"
android:layout_marginRight="10dp"
android:layout_marginBottom="8dp">
</LinearLayout>
</RelativeLayout>
我们还是先说下实现思路吧:首先我们创建一个普通的java类,MyViewPager(既我们抽取的ViewPager实现类)。然后在我们的MainActivity中先创建假数据,然后获取布局实例,将布局,上下文,数据传递给MyViewPager(通过构造传递)。这时MyViewPager已经拿到了我们ViewPager显示需要的数据,那么接下来我们在showViewpager()中进行操作,然后调用showViewpager()这个方法就OK了。当然了我们还需要一个接口,在MainActivity启动时间发消息给MyViewPager通过Handler对图片进行轮播。
这就是实现思路,接下来我们看下代码吧:
MainActivity代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ll_headparent = (LinearLayout) findViewById(R.id.ll_headparent);
rl_head = (RelativeLayout) findViewById(R.id.rl_head);
point = (LinearLayout) findViewById(R.id.index_point);
ViewPager viewpager = (ViewPager) findViewById(R.id.viewpager);
recycler = (WrapRecyclerView) findViewById(R.id.recycler);
initData();
// 拿到MyViewPager实例,传送数据
MyViewPager mMyViewPager = new MyViewPager(this,viewpager,mList,point);
// 显示ViewPager
mMyViewPager.showViewpager();
}
private int[] banner = new int[] {R.mipmap.banner1,R.mipmap.banner2,R.mipmap.banner3};
private void initData(){
mList = new ArrayList<Integer>();
for (int i = 0; i < 3; i++) {
mList.add(banner[i]);
}
}
@Override
protected void onStart() {
super.onStart();
// 开始轮播
mStartViewpager.startViewpager(true);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 停止轮播
mStartViewpager.startViewpager(false);
}
@Override
protected void onPause() {
super.onPause();
// 停止轮播
mStartViewpager.startViewpager(false);
}
//下面是回调接口:
private StartViewpager mStartViewpager;
public interface StartViewpager{
void startViewpager(boolean isStart);
}
public void setStartViewpager(StartViewpager mStartViewpager){
this.mStartViewpager = mStartViewpager;
}
MyViewPager代码,需要实现 MainActivity.StartViewpager接口
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
mViewPager.setCurrentItem(mViewPager.getCurrentItem()+1);
handler.sendEmptyMessageDelayed(0,2000);
}
};
public MyViewPager(Context context,ViewPager viewPager,ArrayList<Integer> list,LinearLayout point){
this.mContext = context;
this.mViewPager = viewPager;
this.mArrayList = list;
this.mPoint = point;
((MainActivity)mContext).setStartViewpager(MyViewPager.this);
}
public void showViewpager(){
mViewPager.setCurrentItem(mArrayList.size() * 500);
initPoint();
mViewPager.setAdapter(new MyViewpagerAdapter());
initViewPagetEvent();
}
// 初始化底部的指示点
private void initPoint(){
for (int i = 0; i < mArrayList.size(); i++) {
ImageView pointImage = new ImageView(mContext);
pointImage.setImageResource(R.drawable.fragment_index_point);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);
params.rightMargin=10;
if (i > 0){
params.rightMargin = 10;
pointImage.setEnabled(false);
}
pointImage.setLayoutParams(params);
mPoint.addView(pointImage);
}
}
// viewpager的adapter
private class MyViewpagerAdapter extends PagerAdapter{
@Override
public int getCount() {
return mArrayList.size() * 1000;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
int pos = position % mArrayList.size();
ImageView imageView = new ImageView(mContext);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
for (int i = 0; i < mArrayList.size(); i++) {
Integer integer = mArrayList.get(pos);
imageView.setImageResource(integer);
}
container.addView(imageView);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}
// 下面是对ViewPager的滑动和手势的处理
private void initViewPagetEvent() {
mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
position = position % mArrayList.size();
mPoint.getChildAt(position).setEnabled(true);
mPoint.getChildAt(currentPoint).setEnabled(false);
currentPoint = position;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
@Override
public void onPageScrollStateChanged(int state) {}
});
mViewPager.setOnTouchListener(new View.OnTouchListener() {
int startX = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
handler.removeCallbacksAndMessages(null);
startX = (int) event.getX();
break;
case MotionEvent.ACTION_CANCEL:
handler.sendEmptyMessageDelayed(0, 2000);
break;
case MotionEvent.ACTION_UP:
int endX = (int) event.getX();
int moveX = endX - startX;
if (Math.abs(moveX) < 5) {
// viewpager的点击事件
Toast.makeText(mContext,"我是头布局:" + mArrayList.get(currentPoint),Toast.LENGTH_SHORT).show();
} else {
handler.sendEmptyMessageDelayed(0, 2000);
}
break;
}
return false;
}
});
}
// 实现接口方法
@Override
public void startViewpager(boolean isStart) {
if (isStart){
handler.sendEmptyMessageDelayed(0, 2000);
initViewPagetEvent();
}else{
handler.removeCallbacksAndMessages(null);
}
}
这是初始化指示点时间用到的布局
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_point" android:state_enabled="true"></item>
<item android:drawable="@drawable/default_point"></item>
</selector>
// default_point
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<size android:height="7dp" android:width="7dp"></size>
<solid android:color="#6c6c6c"></solid>
<stroke android:width="1dp" android:color="#c0c0c0"/>
</shape>
// selected_point
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<size android:height="7dp" android:width="7dp"></size>
<solid android:color="#ffffff"></solid>
</shape>
代码不难,相信大家都能看懂。然后友情提示下:这个抽取没有考虑到当banner只有一张时间的情况,大家做时间可以注意下。那么下篇会讲下将这个viewpager当做head添加给RecyclerView。然后代码也会在下篇一起给出。如果有哪里不足,欢迎大家指教。