自定义广告图片轮播View——CarouselView
2018-08-08 本文已影响0人
饮水思源为名
因为一个广告机的需求,需要做一个广告轮播的效果,不需要什么特别的动画,正常的轮播就可以了。笔者看了网上很多文章,要么不好用,要么就是效果太多,太复杂,用不上。索性自己写了一个简单的View,可以支持普通的广告轮播,目的在轻量级,使用简单。
效果图:

简单说下需求:
- 底部Item指示器
- 图片文字描述显示
- 图片轮播
- 使用简单,使用者不需要考虑除了放图片以外的任何逻辑
重点实现:
- 首先是改View的xml,CarouselView中封装了ViewPager,利用了ViewPager实现轮播
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/view_carousel_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="vertical"
android:layout_alignParentBottom="true"
android:padding="5dp"
android:background="#6000"
android:gravity="center_horizontal">
<TextView
android:id="@+id/view_carousel_tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff" />
<LinearLayout
android:id="@+id/view_carousel_ll_point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="5dp">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
- 绘制指示器,样式是用的drawable做的enable和disenable两种状态的小圆点。然后放入ll_point的LinearLayout,利用Java代码绘制的ImageView。
private void initView(){
viewPager.setOnPageChangeListener(this);
imageViews=new ArrayList<>();
ImageView imageView;
View pointView;
for (int i = 0; i < beans.size(); i++){
//添加图片到集合中
imageView = new ImageView(mC);
imageView.setBackgroundResource(beans.get(i).getImgResource());
imageViews.add(imageView);
//加小白点,指示器(这里的小圆点定义在了drawable下的选择器中了,也可以用小图片代替)
pointView = new View(mC);
pointView.setBackgroundResource(R.drawable.carousel_point); //使用选择器设置背景
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(8, 8);
if (i != 0){
//如果不是第一个点,则设置点的左边距
layoutParams.leftMargin = 10;
}
pointView.setEnabled(false); //默认都是暗色的
ll_point.addView(pointView, layoutParams);
}
if(imageViews.size()>0) Log.i(TAG,"initView完成");
}
- 实现PageChangeListener的onPageSelected方法,这里虽然效果是轮播,单从代码逻辑来讲,是将图片*n然后按顺序排成一排,然后每次展示下一幅图。所以我们需要控制position的值防止下标越界。
@Override
public void onPageSelected(int position) {
//当前的位置可能很大,为了防止下标越界,对要显示的图片的总数进行取余
int newPosition = position % beans.size();
//设置描述信息
tv_desc.setText(beans.get(newPosition).getImgDescs());
//设置小圆点为高亮或暗色
ll_point.getChildAt(lastPosition).setEnabled(false);
ll_point.getChildAt(newPosition).setEnabled(true);
lastPosition = newPosition; //记录之前的点
}
- 用循环+线程+handler实现轮播
private void startCarousel(){
Log.i(TAG,"CarouselView轮播开启");
new Thread(){
@Override
public void run() {
while(isRunning){
try {
Thread.sleep(intervalsTime);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 0:
viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
break;
}
}
};
使用方法:
使用方法就很简单了,毕竟只是为了做一个轮播空间,没有更多的拓展和花样的动画。
- 首先在xml中引用CarouselView
<com.wusy.adv.CarouselView
android:id="@+id/activity_main_carouselView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
- 在Activity中获取引用的CarouselView,构建CarouselBean的ArrayList,调用CarouselView的init方法完成。
carouselView=findViewById(R.id.activity_main_carouselView);
ArrayList<CarouselView.CarouselBean> beans=new ArrayList<>();
beans.add(new CarouselView.CarouselBean(R.mipmap.img1,"第一张图"));
beans.add(new CarouselView.CarouselBean(R.mipmap.img2,"第二张图"));
beans.add(new CarouselView.CarouselBean(R.mipmap.img3,"第三张图"));
beans.add(new CarouselView.CarouselBean(R.mipmap.img4,"第四张图"));
beans.add(new CarouselView.CarouselBean(R.mipmap.img5,"第五张图"));
carouselView.init(beans,3000);//第一个参数是图片集合,第二个参数是轮播间隔时间,单位毫秒
源码:
carousel_point.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/carousel_point_enable"/>
<item android:state_enabled="false" android:drawable="@drawable/carousel_point_disenable"/>
</selector>
carousel_point_disenable.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="8dp"/>
<solid android:color="@android:color/darker_gray"/>
</shape>
carousel_point_enable.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="8dp"/>
<solid android:color="#fff"/>
</shape>
CarouselView:
package com.wusy.adv;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by XIAO RONG on 2018/8/8.
*/
public class CarouselView extends LinearLayout implements ViewPager.OnPageChangeListener {
private String TAG="CarouselView";
private Context mC;
private ViewPager viewPager;
private LinearLayout ll_point;
private TextView tv_desc;
private ArrayList<ImageView> imageViews; //存放图片的集合
private ArrayList<CarouselBean> beans;
private int lastPosition;
private boolean isRunning = true;
private int intervalsTime=5000;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 0:
viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
break;
}
}
};
public CarouselView(Context context) {
this(context,null);
}
public CarouselView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public CarouselView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater.from(context).inflate(R.layout.view_carousel, this);
this.mC=context;
findView();
}
private void findView(){
viewPager=findViewById(R.id.view_carousel_viewpager);
tv_desc=findViewById(R.id.view_carousel_tv_desc);
ll_point=findViewById(R.id.view_carousel_ll_point);
}
public void init(ArrayList<CarouselBean> beans,int intervalsTime){
if(intervalsTime>1000)this.intervalsTime=intervalsTime;
this.beans=beans;
initView();
initAdapter();
startCarousel();
}
/**
* 是否开启轮播
* @param isRunning
*/
public void isRunningCarousel(boolean isRunning){
this.isRunning=isRunning;
}
/**
* 初始化适配器
*/
private void initAdapter() {
ll_point.getChildAt(0).setEnabled(true);//初始化控件时,设置第一个小圆点为亮色
tv_desc.setText(beans.get(0).getImgDescs()); //设置第一个图片对应的文字
lastPosition=0;
viewPager.setAdapter(new CarouseAdapter());
Log.i(TAG,"initAdapter()完成");
}
/**
* 初始化控件
*/
private void initView(){
viewPager.setOnPageChangeListener(this);
imageViews=new ArrayList<>();
ImageView imageView;
View pointView;
for (int i = 0; i < beans.size(); i++){
//添加图片到集合中
imageView = new ImageView(mC);
imageView.setBackgroundResource(beans.get(i).getImgResource());
imageViews.add(imageView);
//加小白点,指示器(这里的小圆点定义在了drawable下的选择器中了,也可以用小图片代替)
pointView = new View(mC);
pointView.setBackgroundResource(R.drawable.carousel_point); //使用选择器设置背景
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(8, 8);
if (i != 0){
//如果不是第一个点,则设置点的左边距
layoutParams.leftMargin = 10;
}
pointView.setEnabled(false); //默认都是暗色的
ll_point.addView(pointView, layoutParams);
}
if(imageViews.size()>0) Log.i(TAG,"initView完成");
}
/**
* 开启轮播
*/
private void startCarousel(){
Log.i(TAG,"CarouselView轮播开启");
new Thread(){
@Override
public void run() {
while(isRunning){
try {
Thread.sleep(intervalsTime);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
//页面滑动
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//新的页面被选中
@Override
public void onPageSelected(int position) {
//当前的位置可能很大,为了防止下标越界,对要显示的图片的总数进行取余
int newPosition = position % beans.size();
//设置描述信息
tv_desc.setText(beans.get(newPosition).getImgDescs());
//设置小圆点为高亮或暗色
ll_point.getChildAt(lastPosition).setEnabled(false);
ll_point.getChildAt(newPosition).setEnabled(true);
lastPosition = newPosition; //记录之前的点
}
//页面滑动状态发生改变
@Override
public void onPageScrollStateChanged(int state) {
}
private class CarouseAdapter extends PagerAdapter{
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
//从集合中获得图片
int newPosition = position % imageViews.size(); //数组中总共有5张图片,超过数组长度时,取摸,防止下标越界
ImageView imageView = imageViews.get(newPosition);
//把图片添加到container中
container.addView(imageView);
//把图片返回给框架,用来缓存
return imageView;
}
//销毁条目
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//object:刚才创建的对象,即要销毁的对象
container.removeView((View) object);
}
}
public static class CarouselBean{
private int imgResource;
private String imgDescs;
public int getImgResource() {
return imgResource;
}
public void setImgResource(int imgResource) {
this.imgResource = imgResource;
}
public String getImgDescs() {
return imgDescs;
}
public void setImgDescs(String imgDescs) {
this.imgDescs = imgDescs;
}
public CarouselBean(int imgResource, String imgDescs) {
this.imgResource = imgResource;
this.imgDescs = imgDescs;
}
}
}