学习使用自定义View实现一个可以自动无限循环轮播的广告轮播图,效果图如下:
具体实现思路:
- 首先利用view pager实现图片轮播
- 使用handle发送延时消息来实现图片自动播放
- 通过设置viewpager的item数量为Integer.MAX_VALUE,然后在adapter中获取当前位置item的方法里对position和我们实际的item数量进行求余来获取当前的item,以此达到无限循环滚动的效果
完整代码如下:
package com.car.customview;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.car.customview.adapter.MyPageAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* Created by pulian on 2019/2/26.
* 无限循环自动轮播的广告条
* 自动循环的方式:1.Timer 2.开子线程 无限循环 3.ClockManager 4.handler发送延时消息
*/
public class Banner extends AppCompatActivity {
private final static int MSG_CHANGE_PAGE = 0;
//图片切换时间
private final long interval = 2000;
private ViewPager viewPager;
//指示点容器
private LinearLayout pointGroup;
private TextView imgDesc;
private List<ImageView> imgList;
private MyPageAdapter adapter;
//上一次view pager item的位置
private int lastPagePosition = 0;
private boolean isRunning = false;
//图片资源
private final int[] imgIds = {R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e};
//文字资源
private final String[] msgs = {"巩俐不低俗,我就不能低俗", "朴树又回来了,引发万人大合唱",
"揭秘北京电影如何升级", "乐视TV大放送", "屌丝的逆袭"};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
initView();
initData();
isRunning = true;
handler.sendEmptyMessageDelayed(MSG_CHANGE_PAGE, interval);
}
private void initData() {
imgList = new ArrayList<>();
imgDesc.setText(msgs[0]);
for (int i = 0; i < imgIds.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(imgIds[i]);
imgList.add(imageView);
//添加指示点
ImageView point = new ImageView(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20, 20);
params.rightMargin = 20;
point.setLayoutParams(params);
point.setBackgroundResource(R.drawable.point_bg);
if (i == 0) {
point.setEnabled(true);
} else {
point.setEnabled(false);
}
pointGroup.addView(point);
}
adapter = new MyPageAdapter(imgList);
viewPager.setAdapter(adapter);
//无限循环播放初始化第一个位置
viewPager.setCurrentItem(Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2) % imgList.size());
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
//对position求余换算出实际的位置
position = position % imgList.size();
imgDesc.setText(msgs[position]);
//改变指示点的状态
pointGroup.getChildAt(position).setEnabled(true);
pointGroup.getChildAt(lastPagePosition).setEnabled(false);
lastPagePosition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void initView() {
viewPager = findViewById(R.id.view_pager);
pointGroup = findViewById(R.id.point_group);
imgDesc = findViewById(R.id.msg);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MSG_CHANGE_PAGE:
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1);
if (isRunning){
handler.sendEmptyMessageDelayed(MSG_CHANGE_PAGE, interval);
}
break;
}
}
};
@Override
protected void onDestroy() {
isRunning = false;
super.onDestroy();
}
}
viewpager的adapter代码:
package com.car.customview.adapter;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import java.util.List;
public class MyPageAdapter extends PagerAdapter {
private List<ImageView> mList;
private int count;
public MyPageAdapter(List<ImageView> list) {
mList = list;
count = mList.size();
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView(mList.get(position % count));
object = null;
}
/*
获得相应位置上的view
*/
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
container.addView(mList.get(position % count));
return mList.get(position % count);
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="200dp">
</android.support.v4.view.ViewPager>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_alignBottom="@id/view_pager"
android:background="#33000000">
<TextView
android:id="@+id/msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/app_name"
android:textColor="@android:color/white"
android:textSize="18sp"/>
<LinearLayout
android:id="@+id/point_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
用到的drawable文件:
两种状态的指示点
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size android:width="5dp" android:height="5dp"/>
<solid android:color="#aaFFFFFF"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<size android:width="5dp" android:height="5dp"/>
<solid android:color="#55000000"/>
</shape>
指示点选择器
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/point_normal" android:state_enabled="false"/>
<item android:drawable="@drawable/point_focused" android:state_enabled="true"/>
</selector>