在实际应用中,banner轮播图是必不可少的东西,首页的话可能需要点击跳转广告等,或者在某项内容内可以点击浏览大图手势放大缩小等那么这些功能虽然不难但是写起来很麻烦,于是我封装了下,方便引用以后,首先直接上代码吧,里面用到的一些类下面就讲解
首先你可能需要在values下的attr添加以下代码(没有attr就新建一个):
//标题
//是否可以点击浏览大图
//是否自动轮播
//是否缓存本地
//标题大小
//标题颜色
//左边文字大小
//左边背景
//左边文字
//右边文字颜色
//右边背景
//右边文字
下面直接上工具类代码
package com.demo.banner;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.bumptech.glide.Glide;
import com.sanshi.repairOrder.adapter.PictureAdapter;
import com.sanshi.repairOrder.api.StaticUtil;
import com.sanshi.repairOrder.bean.BannerBean;
import com.sanshi.repairOrder.custom.picDialog.PicShowDialog;
import com.sanshi.repairOrder.custom.picDialog.bean.ImageInfo;
import com.sanshi.repairOrder.util.apiUtil.OtherUtil;
import com.sanshi.repairOrder.util.glideImageToLocal.DownLoadImageService;
import com.sanshi.repairOrder.util.glideImageToLocal.ImageDownLoadCallBack;
import com.sanshi.repairOrder.util.log.TLog;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Created by CherishTang on 2018/3/15.
* 自定义banner轮播图
*/
public class CustomBannerPicture extends RelativeLayout implements View.OnClickListener, MyViewPager.OnImageItemClickListener {
private Context mContext;
private ViewGroup.LayoutParams matchParams = new
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
private List images = new ArrayList<>();
private MyViewPager viewPager;
private LinearLayout dots_layout;
private boolean isBrowse = false, isAutoBanner = true, isDownLoadLoacl = false;
private List imageInfosList = new ArrayList<>();
private int mCurrentPosition = 0;
private List imgPic;
public CustomBannerPicture(Context context) {
super(context);
}
public CustomBannerPicture(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public void init(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Topbar);
isBrowse = ta.getBoolean(R.styleable.Topbar_isBrowse, false);
isAutoBanner = ta.getBoolean(R.styleable.Topbar_isAutoBanner, false);
isDownLoadLoacl = ta.getBoolean(R.styleable.Topbar_isDownLoadLocal, false);
this.mContext = context;
setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, R.dimen.x392));
}
public void initView(List imgPic) {
this.imgPic = imgPic;
if (!imgPic.isEmpty() && imgPic.size() != 0) {
if (imgPic.size() == 1) {
ImageView imageView = new ImageView(mContext);
imageView.setLayoutParams(matchParams);
Object imgPath = imgPic.get(0).getPath() == null ? imgPic.get(0).getLocalPath() : imgPic.get(0).getPath();
Glide.with(mContext)
.load(imgPath)
.placeholder(R.mipmap.icon_banner_default)
.error(R.mipmap.icon_banner_default)
.into(imageView);
imageInfosList.add(new ImageInfo(imgPath, 200, 200));
if (isDownLoadLoacl)
downloadPic(imgPic.get(0).getPath() == null ? imgPic.get(0).getLocalPath() : imgPic.get(0).getPath());
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
addView(imageView);
if (isBrowse) imageView.setOnClickListener(this);
} else {
images.clear();
for (int k = 0; k < imgPic.size(); k++) {
Object imgPath = imgPic.get(k).getPath() == null ? imgPic.get(k).getLocalPath() : imgPic.get(k).getPath();
imageInfosList.add(new ImageInfo(imgPath, 200, 200));
if (isDownLoadLoacl) downloadPic(imgPath);
getImages(imgPath);
}
addHeader();
}
}
}
/**
* 创建ViewPager的子item项
*/
private void getImages(Object oldPath) {
ImageView img1 = new ImageView(mContext);
img1.setLayoutParams(matchParams);
if (isBrowse) img1.setOnClickListener(this);
Glide.with(mContext).load(oldPath).error(R.mipmap.icon_banner_default).into(img1);
img1.setScaleType(ImageView.ScaleType.FIT_XY);
images.add(img1);
}
public ViewPager getViewPager() {
return viewPager;
}
public int getCurrentPosition() {
return mCurrentPosition;
}
/**
* 填充布局
*/
private void addHeader() {
View headerView = LayoutInflater.from(mContext).inflate(R.layout.viewpager_round_layout_index, null);
LinearLayout images_layout = (LinearLayout) headerView.findViewById(R.id.carousel_image_layout);
dots_layout = (LinearLayout) headerView.findViewById(R.id.image_round_layout);
viewPager = new MyViewPager(mContext, isAutoBanner);
initImageRounds();
viewPager.setImages(images);
viewPager.setOnImageItemClickListener(this);
viewPager.setAdapter(new PictureAdapter(images));
viewPager.setCurrentItem(Integer.MAX_VALUE / 2);
//一个childView只能被赋给一个parent。因此在添加前需要移除,再添加
images_layout.removeAllViews();
removeAllViews();
images_layout.addView(viewPager);
addView(headerView);
}
/**
* 计算viewPager小底部小圆点的大小
*/
private void initImageRounds() {
List dots = new ArrayList<>();
dots_layout.removeAllViews();
/*
*当轮播图大于1张时小圆点显示
*/
if (images.size() > 1) {
dots_layout.setVisibility(View.VISIBLE);
} else {
dots_layout.setVisibility(View.INVISIBLE);
}
for (int i = 0; i < images.size(); i++) {
ImageView round = new ImageView(mContext);
/*
* 默认让第一张图片显示深颜色的圆点
*/
if (i == 0) {
round.setImageResource(R.mipmap.icon_point2);
} else {
round.setImageResource(R.mipmap.icon_point1);
}
dots.add(round);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, -2);
params.leftMargin = 20;
dots_layout.addView(round, params);
}
viewPager.setDots(dots);
}
//缓存图片至本地
public void downloadPic(Object pic) {
DownLoadImageService service = new DownLoadImageService(mContext, pic,
StaticUtil.ROOTFILEPATH + File.separator + "bannerPic" + File.separator, new ImageDownLoadCallBack() {
@Override
public void onDownLoadSuccess(File file) {
// BannerBean bannerBean = new BannerBean();
// bannerBean.setModifyTime(System.currentTimeMillis());
// bannerBean.setPath(file.getPath());
// dataBaseOperate.insertToBanner(bannerBean);
}
@Override
public void onDownLoadSuccess(Bitmap bitmap) {
}
@Override
public void onDownLoadFailed() {
TLog.show("本地图片缓存失败");
}
});
//千万别忘了启动线程服务
new Thread(service).start();
}
@Override
public void onClick(View v) {
if (imageInfosList == null || imageInfosList.isEmpty()) return;
PicShowDialog dialog = new PicShowDialog(mContext, imageInfosList, mCurrentPosition);
dialog.show();
}
@Override
public void onItemClick(int itemPosition) {
}
@Override
public void getPosition(int itemPosition) {
mCurrentPosition = itemPosition;//把viewPager当前的position传递出去,viewPager.getCurrentItem()获取的位置是不准确的
try {
if (!isBrowse)
OtherUtil.reqBrowser(mContext, imgPic.get(mCurrentPosition).getLinkPath(), false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
首先在app下的build.gradle下添加,这是一个图片处理工具
compile 'com.github.bumptech.glide:glide:3.7.0'
banner图布局代码如下尺寸可以根据自己ui的设计进行适配,另外至于圆点的图片大家可以自己制作了
<你的包名路径.CustomBannerPicture
android:id="@+id/customBannerPicture"
android:layout_width="match_parent"
app:isBrowse="true"
app:isAutoBanner="true"
app:isDownLoadLocal="true"
android:layout_height="wrap_content"/>
这样我们一个自定义的banner图就写好了,在activity或fragment中我们这样初始化一下即可
List bannerBeanList = new ArrayList<>();
bannerBeanList.add(new BannerBean("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1521709311&di=426d774dfbc52e74cb35a72105d4a9a1&imgtype=jpg&er=1&src=http%3A%2F%2Fi2.hdslb.com%2Fbfs%2Farchive%2F48e9bf876a2b0768153e45503f9b56aaa9e6d2f0.jpg"));
bannerBeanList.add(new BannerBean("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1521709327&di=b7284ff723a0854289b2e51cb8b54b95&imgtype=jpg&er=1&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fw%3D580%2Fsign%3D18a37e195282b2b7a79f39cc01accb0a%2Fe39e1312b07eca80dcdfdffa9a2397dda0448362.jpg"));
bannerBeanList.add(new BannerBean("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1521114631940&di=a2a484cc87bbb67f954ec99fbfaf4dae&imgtype=0&src=http%3A%2F%2Fi1.hdslb.com%2Fbfs%2Farchive%2F7b4b2aec04f531bca94431d6283f43d3c47d3e3c.jpg"));
customBannerPicture.initView(bannerBeanList);
/**
* Created by CherishTang on 2017/6/14.
* 首页banner图
*/
public class BannerBean {
private long modifyTime;
private String path;
private String imgDiscribe;//图片描述
private String linkPath;//点击图片跳转的页面地址
private @DrawableRes
int localPath;
public BannerBean() {
}
public BannerBean(String path) {
this.path = path;
}
public BannerBean(int localPath) {
this.localPath = localPath;
}
public String getImgDiscribe() {
return imgDiscribe;
}
public void setImgDiscribe(String imgDiscribe) {
this.imgDiscribe = imgDiscribe;
}
public String getLinkPath() {
return linkPath;
}
public void setLinkPath(String linkPath) {
this.linkPath = linkPath;
}
public int getLocalPath() {
return localPath;
}
public void setLocalPath(int localPath) {
this.localPath = localPath;
}
public long getModifyTime() {
return modifyTime;
}
public void setModifyTime(long modifyTime) {
this.modifyTime = modifyTime;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
import android.support.annotation.DrawableRes;
/**
* 圈子:九宫格图片展示,Image封装
* Created by xiaoke on 2016/5/9.
*/
public class ImageInfo {
private Object url;
private int width;
private int height;
private @DrawableRes int imgRes;
public ImageInfo(Object url, int width, int height) {
this.url = url;
this.width = width;
this.height = height;
}
public ImageInfo(int imgRes, int width, int height ) {
this.width = width;
this.height = height;
this.imgRes = imgRes;
}
public int getImgRes() {
return imgRes;
}
public void setImgRes(int imgRes) {
this.imgRes = imgRes;
}
public Object getUrl() {
return url;
}
public void setUrl(Object url) {
this.url = url;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public String toString() {
return "image---->>url="+url+"width="+width+"height"+height;
}
package com.demo.banner;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.widget.ImageView;
import java.util.Date;
import java.util.List;
/**
* Created by CherishTang on 2016/8/19.
*
*/
public class MyViewPager extends ViewPager {
/**
* 图片和小圆点
*/
private List images;
private List dots;
/**
* 停止轮播的标记
*/
private boolean stopLoopTag = false;
/**
* lastPointPosition 上一个点的位置,初始化为0
* lastPointIndex 上一个点在集合中的位置
* currentPointIndex 当前的点在集合中的位置
*/
private int lastPointPosition = 0;
private int lastPointIndex;
private int currentPointIndex;
/**
* 记录点击时的坐标
*/
private int xDown;
private int yDown;
/**
* 用于处理手势事件
*/
private long touchTime;
private boolean timeTag;
private TimeThread timeThread;
private boolean isOpen;
public MyViewPager(Context context, boolean isOpen) {
super(context);
initLoop();
this.isOpen = isOpen;
if (!isOpen) stopLoop();
addOnPageChangeListener(onPageChangeListener);
}
public List getImages() {
return images;
}
public void setImages(List images) {
this.images = images;
}
public void setDots(List dots) {
this.dots = dots;
}
/**
* 处理轮播的Handler
*/
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
if (msg.what == 10 && !stopLoopTag) {
setCurrentItem(msg.arg1);
} else {
mHandler.removeMessages(10);
}
return true;
}
});
private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
/**
* 改变小圆点的状态
* 三种情况:
* 1.在初始位置
* 2.向左滑动
* 3.向右滑动
* 不要放在上一个方法中,会有明显的延迟现象出现
* lastPointPosition 上一个点的位置,初始化为0
* lastPointIndex 上一个点在集合中的位置
* currentPointIndex 当前的点在集合中的位置
* */
if (lastPointPosition == 0) {
currentPointIndex = 1;
lastPointIndex = 0;
} else if (lastPointPosition < position) {
if (currentPointIndex == (getImages().size() - 1)) {
currentPointIndex = 0;
} else {
currentPointIndex += 1;
}
} else if (lastPointPosition > position) {
if (currentPointIndex == 0) {
currentPointIndex = getImages().size() - 1;
} else {
currentPointIndex -= 1;
}
}
dots.get(lastPointIndex).setImageResource(R.mipmap.icon_point2);
dots.get(currentPointIndex).setImageResource(R.mipmap.icon_point1);
lastPointPosition = position;
lastPointIndex = currentPointIndex;
if (onImageItemClickListener != null) onImageItemClickListener.getPosition(lastPointIndex);
}
@Override
public void onPageScrollStateChanged(int state) {
}
};
/**
* 停止轮播
*/
public void stopLoop() {
if (!stopLoopTag) {
stopLoopTag = true;
}
}
/**
* 开启轮播
*/
public void openLoop() {
if (stopLoopTag) {
stopLoopTag = false;
}
}
/**
* 手势事件的重写
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
/**
* 按下的时候停止轮播
* */
stopLoop();
xDown = (int) event.getX();
yDown = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
/**
* 这里不用做任何处理,移动的时候ViewPager内的图片会自动滑动
* */
break;
case MotionEvent.ACTION_UP:
if (isOpen){
/**
* 记录按下时间
* */
if (timeThread == null) {
touchTime = new Date().getTime();
timeTag = true;
timeThread = new TimeThread();
timeThread.start();
} else {
touchTime = new Date().getTime();
}
}
/*
* 判断是否是点击事件
* */
int xUp = (int) event.getX();
int yUp = (int) event.getY();
if (Math.abs(xDown - xUp) < 20 && Math.abs(yDown - yUp) < 20) {
if (onImageItemClickListener != null) {
onImageItemClickListener.onItemClick(currentPointIndex);
}
}
break;
}
return super.onTouchEvent(event);
}
/**
* 初始化轮播
*/
public void initLoop() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
if (!stopLoopTag) {
Message message = Message.obtain();
message.what = 10;
message.arg1 = getCurrentItem() + 1;
mHandler.sendMessage(message);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
/**
* 时间线程,用于记录手指离开点击ViewPager的时间
* 如果离开的时间 >= 2000毫秒,那么ViewPager继续轮播
*/
class TimeThread extends Thread {
@Override
public void run() {
while (timeTag) {
long currentTime = new Date().getTime();
if (currentTime - touchTime >= 2000) {
openLoop();
timeTag = false;
timeThread = null;
}
}
}
}
/**
* 对Activity暴露接口
*/
private OnImageItemClickListener onImageItemClickListener;
public interface OnImageItemClickListener {
void onItemClick(int itemPosition);
void getPosition(int itemPosition);
}
public void setOnImageItemClickListener(OnImageItemClickListener onImageItemClickListener) {
this.onImageItemClickListener = onImageItemClickListener;
}
}
package com.demo.banner;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;
import java.util.List;
/**
* Created by CherishTang
*
* @author CherishTang
*/
public class PictureAdapter extends PagerAdapter {
private List images;
/**
* initPosition -1为初始化的位置,后面是当前的图片索引位置
* topPosition 记录上一次初始化的索引位,用于计算上次的position和本次position的偏移量
*
* */
private int initPosition = -1;
private int topPosition = -1;
public PictureAdapter(List images) {
this.images = images;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
/**
* 实例化Item
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
if(images.size() <=1){
ImageView imageView = images.get(topPosition);
imageView.setAdjustViewBounds(true);
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
container.addView(imageView);
return imageView;
}else{
/*
* 初始化状态
* 向左滑动
* 向右滑动
* 由于ViewPager有预加载机制,默认加载一页,因此在第一次初始化的时候,会调用三次这个方法.
* (第一次: position=1073741823 第二次: position=1073741822 第三次: position=1073741824)
*
* 而后续,这个方法仅被执行一次,并且执行的是预加载下一页的请求.
* */
if (initPosition == -1) {
/**
* 初始化状态
* topPosition 记录第一次初始化的索引位.用于后续作比较判断下次是向右滑动还是向左滑动
* initPosition 初始化图片集合的索引值
* */
topPosition = position;
initPosition = 0;
} else if (topPosition < position) {
/**
* 向左滑动
* 得出偏移量后比较是否超过图片集合的大小
* */
int value = position - topPosition;
initPosition += value;
if (initPosition == images.size()) {
/**
* 滑动到了最后一页
* */
initPosition = 0;
}
if (initPosition > images.size()) {
/**
* 如果超出了图片集合的大小,则 initPosition = 超过的数值
* */
initPosition = (initPosition - images.size());
}
topPosition = position;
} else if (topPosition > position) {
int value = topPosition - position;
initPosition -= value;
if (initPosition == -1) {
/**
* 滑动到了第一页
* */
initPosition = images.size() - 1;
}
if (initPosition < -1) {
/**
* 当计算后的值小于了集合大小,则用集合大小减去小于的这部分
* */
initPosition = (images.size() - (Math.abs(initPosition)));
}
topPosition = position;
}
if(initPosition>(images.size()-1)){
initPosition = 0;
}
/**
* 只用这句话应该会出现问题
* */
// position %= images.size();
// if (position < 0) {
// position = position + images.size();
// }
ImageView imageView = null;
try{
imageView = images.get(initPosition);
ViewParent parent = imageView.getParent();
if (parent != null) {
ViewGroup viewGroup = (ViewGroup) parent;
viewGroup.removeView(imageView);
}
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
container.addView(imageView);
}catch (Exception e){
e.printStackTrace();
}
return imageView;
}
}
}
注意:适配7.0没写,还有缓存本地需要读写权限,动态权限申请自己添加
附上demo地址:https://download.csdn.net/download/fzkf9225/10354103