转载请说明出处:http://blog.csdn.net/ff20081528

前段时间一个朋友问我有没有做过手机商城的广告浏览的功能,如下图:

我也看了下,基本上所有的商城也都有衣蛾这样的东西。在网上搜了下,开源的也有,网友自己写的也有。但是没有找到完全符合朋友需求的一个组件。为此也就花了点时间帮朋友写了这么一个组件,在此分享出来,希望对一些朋友有用,能省一些开发时间。

组件的功能

1,自动播放功能(带有切换动画);

2,手指滑动切换(手指效果和动画效果同步);

3,能够循环滑动和播放;

4,有图片浏览指示标;

组件的实现我在代码里面都有详细的注释,但是要看懂这个组件的源码我还是建议去看看我的上一篇文章《深入了解ViewFlipper工作机制》,要不看起来会很吃力。下面直接贴出源码  转载请说明出处:http://blog.csdn.net/ff20081528

ImageBrowsingViewFlipper.java

package org.sunday.myflipper;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.Animation;
import android.widget.ImageView;
import android.widget.ViewFlipper;
/**
* 图片浏览类
* @author sunday
* 2014-1-13
* zhengchao1937@163.com
* qq:804935743
*/
public class ImageBrowsingViewFlipper extends ViewFlipper {
private final static String TAG = "ImageBrowsingViewFlipper";
/**
* VIEW滚动时的默认速度
*/
private final static int DEFAULT_CROLL_SPEED = 30;
/**
* View滚动时,让线程休眠时间,目的让用户的眼睛可以看到图片滚动的效果
*/
private final static int SLEEP_TIME = 20;
/**
* 图片资源
*/
private Drawable[] imgsDraw;
private Context mContext;
/**
* VIEW滚动时的速度,默认值为DEFAULT_CROLL_SPEED
*/
private int crollSpeed = DEFAULT_CROLL_SPEED;
/**
* 记录手指按下时的X轴的坐标
*/
private float xDown;
/**
* 记录手指移动的时候的X轴的坐标
*/
private float xMove;
/**
* 记录手指抬起时的X轴的坐标
*/
private float xUp;
/**
* ViewFlipperde的宽度
*/
private int vfWidth;
/**
* 图片的数量
*/
private int imgsLen;
/**
* 当前显示的子View
*/
private ImageView ivCurr;
/**
* 下一个将要显示的子View
*/
private ImageView ivNext;
/**
* 之前已经显示过的子View
*/
private ImageView ivLast;
/**
* 当前子View的位置
*/
private int currViewPosition;
/**
* 回调接口
*/
private IImageBrowsingMark mImgBrowsingMark;
/**
* ViewFlipper子View切换时将要显示的View的进入动画
*/
private Animation lInAnim;
/**
* ViewFlipper子View切换时当前显示的View的退出动画
*/
private Animation lOutAnim;
public ImageBrowsingViewFlipper(Context context) {
super(context);
mContext = context;
init();
}
public ImageBrowsingViewFlipper(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
init();
}
/**
* 设置View滚动时的速度
* @param crollSpeed
*/
public void setCrollSpeed(int crollSpeed) {
this.crollSpeed = crollSpeed;
}
public int getVfWidth() {
return vfWidth;
}
public void setImgsDraw(Drawable[] imgsDraw) {
this.imgsDraw = imgsDraw;
initImages();
}
public void setVfWidth(int vfWidth) {
this.vfWidth = vfWidth;
}
public IImageBrowsingMark getmImgBrowsingMark() {
return mImgBrowsingMark;
}
public void setmImgBrowsingMark(IImageBrowsingMark mImgBrowsingMark) {
this.mImgBrowsingMark = mImgBrowsingMark;
}
private void init() {
//视图树观察者,用于获取ViewFlipper的宽度
ViewTreeObserver vto = getViewTreeObserver();
//当一个视图树将要绘制时,所要调用的回调函数的接口类
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
int height = ImageBrowsingViewFlipper.this.getMeasuredHeight();
int width =ImageBrowsingViewFlipper.this.getMeasuredWidth();
Log.e(TAG, "height = " + height + " ; width = " + width);
vfWidth = width;
return true;
}
});
}
/**
* 初始化Image
*/
private void initImages() {
imgsLen = imgsDraw.length;
// 添加图片源
for (int i = 0; i < imgsLen; i++) {
ImageView iv = new ImageView(mContext);
iv.setOnTouchListener(onTouchListener);
iv.setImageDrawable(imgsDraw[i]);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
addView(iv, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
}
/**
* 停止滑动和动画并保存动画
*/
private void stopAndSaveAnimation() {
ImageBrowsingViewFlipper.this.stopFlipping();
if(lInAnim == null && lOutAnim == null) {
lInAnim = ImageBrowsingViewFlipper.this.getInAnimation();
lOutAnim = ImageBrowsingViewFlipper.this.getOutAnimation();
}
ImageBrowsingViewFlipper.this.setInAnimation(null);
ImageBrowsingViewFlipper.this.setOutAnimation(null);
}
/**
* 开启滑动并使用动画
*/
private void startAndUseAnimation() {
ImageBrowsingViewFlipper.this.startFlipping();
ImageBrowsingViewFlipper.this.setInAnimation(lInAnim);
ImageBrowsingViewFlipper.this.setOutAnimation(lOutAnim);
}
/**
* 实现OnTouchListener事件
*/
private OnTouchListener onTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
//手指按下时的逻辑
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "MotionEvent.ACTION_DOWN" );
xDown = event.getRawX();
stopAndSaveAnimation();
break;
//手指移动时的逻辑
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "ACTION_MOVE" );
xMove = event.getRawX();
//手指滑动的距离
int xDistance = (int)(xMove - xDown);
Log.e(TAG, "-----------------  xDown = " + xDown + "; xMove = " + xMove);
//当前显示的ImageView
ImageView ivCurr = (ImageView) ImageBrowsingViewFlipper.this.getCurrentView();
currViewPosition = ImageBrowsingViewFlipper.this.getDisplayedChild();
//下一个ImageView
ImageView ivNext = getNextView(currViewPosition);
//上一个ImageView
ImageView ivLast = getLastView(currViewPosition);
//在ViewFlipper工作机制中,某一个时间点只有当前的子View是VISIBLE状态,其他的子View都是GONE状态。
//所以要在滑动的时候看见他们,必须将他们设置为VISIBLE状态
ivNext.setVisibility(View.VISIBLE);
ivLast.setVisibility(View.VISIBLE);
//将当前的ImageView移动到这个(-xDistance, 0)位置
ivCurr.scrollTo(-xDistance, 0);
//将下一个ImageView移动到(xNext, 0)位置
int xNext = - vfWidth - xDistance;
Log.e(TAG, "xNext = " + xNext);
ivNext.scrollTo(xNext, 0);
//将上一个ImageView移动到(xLast, 0)位置
int xLast = vfWidth - xDistance;
Log.e(TAG, "xLast = " + xLast);
ivLast.scrollTo(xLast, 0);
break;
//手指抬起时的逻辑
case MotionEvent.ACTION_UP:
Log.e(TAG, "ACTION_UP" );
xUp = event.getRawX();
//判断用户手指的意图,这块可以自己改写逻辑
if(wantToNext()) {
Log.e(TAG, "wantToNext-------------");
new ScrollToNextTask().execute(crollSpeed);
} else if(wantToLast()) {
Log.e(TAG, "wantToLast-------------");
new ScrollToLastTask().execute(crollSpeed);
} else {
new ScrollToLastTask().execute(crollSpeed);
}
break;
default:
break;
}
return true;
}
};
/**
*  判断当前手势的意图是不是想显示上一个子View
* @return 当前手势想移动到上一个则返回true,否则返回false。
*/
protected boolean wantToLast() {
return xUp - xDown > 0;
}
/**
*  判断当前手势的意图是不是想显示下一个子View
* @return 当前手势想移动到下一个则返回true,否则返回false。
*/
protected boolean wantToNext() {
return xUp - xDown < 0;
}
/**
* 得到上一个子视图的ImageView对象
* @param currViewPosition 当前View的位置
* @return 子视图对象
*/
private ImageView getLastView(int currViewPosition) {
int lastViewPosition = currViewPosition - 1;
if(currViewPosition == 0) {
lastViewPosition = imgsLen - 1;
}
Log.e(TAG, "lastViewPosition = " + lastViewPosition);
return (ImageView) this.getChildAt(lastViewPosition);
}
/**
* 得到下一个子视图的ImageView对象
* @param currViewPosition 当前View的位置
* @return 子视图对象
*/
private ImageView getNextView(int currViewPosition) {
int nextViewPosition = currViewPosition + 1;
if(currViewPosition == imgsLen - 1) {
nextViewPosition = 0;
}
Log.e(TAG, "nextViewPosition = " + nextViewPosition);
return (ImageView) this.getChildAt(nextViewPosition);
}
/**
* 意图显示下一个子View
* @author sunday
*
*/
class ScrollToNextTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
ivCurr = (ImageView) ImageBrowsingViewFlipper.this.getCurrentView();
int currViewPosition = ImageBrowsingViewFlipper.this.getDisplayedChild();
ivNext = getNextView(currViewPosition);
ivLast = getLastView(currViewPosition);
int xDistance = Math.abs((int)(xUp - xDown));
while (true) {
xDistance = xDistance + speed[0];
if(xDistance > vfWidth) {
xDistance = vfWidth;
break;
}
publishProgress(xDistance);
sleep(SLEEP_TIME);
}
return xDistance;
}
@Override
protected void onProgressUpdate(Integer... xDistance) {
int xNext = - vfWidth + xDistance[0];
Log.e(TAG, "xNext = " + xNext);
ivCurr.scrollTo(xDistance[0], 0);
ivNext.scrollTo(xNext, 0);
}
@Override
protected void onPostExecute(Integer xDistance) {
int xNext = - vfWidth + xDistance;
Log.e(TAG, "xNext = " + xNext);
ivCurr.scrollTo(xDistance, 0);
ivNext.scrollTo(xNext, 0);
int currPosition = displayedNextChild(currViewPosition);
ImageBrowsingViewFlipper.this.setDisplayedChild(currPosition);
ivNext.setVisibility(View.VISIBLE);
if(null != mImgBrowsingMark.getMarkView())
mImgBrowsingMark.getMarkView().setMark(currPosition);
ivCurr.setVisibility(View.GONE);
ivLast.setVisibility(View.GONE);
//将当前(移动发生之前)的ImageView移动到(0,0)位置因为在滑动时它的位置被改变
ivCurr.scrollTo(0, 0);
//将上一个(移动发生之前)的ImageView移动到(0,0)位置
ivLast.scrollTo(0, 0);
startAndUseAnimation();
}
}
/**
* 意图显示上一个子View
* @author sunday
*
*/
class ScrollToLastTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
ivCurr = (ImageView) ImageBrowsingViewFlipper.this.getCurrentView();
int currViewPosition = ImageBrowsingViewFlipper.this.getDisplayedChild();
ivNext = getNextView(currViewPosition);
ivLast = getLastView(currViewPosition);
int xDistance = Math.abs((int)(xUp - xDown));
while (true) {
xDistance = xDistance + speed[0];
if(xDistance > vfWidth) {
xDistance = vfWidth;
break;
}
publishProgress(xDistance);
sleep(SLEEP_TIME);
}
return xDistance;
}
@Override
protected void onProgressUpdate(Integer... xDistance) {
int xLast = vfWidth - xDistance[0];
Log.e(TAG, "xLast = " + xLast);
ivCurr.scrollTo(-xDistance[0], 0);
ivLast.scrollTo(xLast, 0);
}
@Override
protected void onPostExecute(Integer xDistance) {
int xLast = vfWidth - xDistance;
Log.e(TAG, "xLast = " + xLast);
ivCurr.scrollTo(-xDistance, 0);
ivLast.scrollTo(xLast, 0);
int currPosition = displayedLastChild(currViewPosition);
ImageBrowsingViewFlipper.this.setDisplayedChild(currPosition);
ivLast.setVisibility(View.VISIBLE);
if(null != mImgBrowsingMark.getMarkView())
mImgBrowsingMark.getMarkView().setMark(currPosition);
ivCurr.setVisibility(View.GONE);
ivNext.setVisibility(View.GONE);
ivCurr.scrollTo(0, 0);
ivNext.scrollTo(0, 0);
startAndUseAnimation();
}
}
/**
* 视图向左滑动将要显示的子视图的位置
* @param currViewPosition
* @return
*/
private int displayedNextChild(int currViewPosition) {
int nextViewPosition = currViewPosition + 1;
if(currViewPosition == imgsLen - 1) {
nextViewPosition = 0;
}
return nextViewPosition;
}
/**
* 视图向右滑动将要显示的子视图的位置
* @param currViewPosition
* @return
*/
private int displayedLastChild(int currViewPosition) {
int lastViewPosition = currViewPosition - 1;
if(currViewPosition == 0) {
lastViewPosition = imgsLen - 1;
}
return lastViewPosition;
}
/**
* 使当前线程睡眠指定的毫秒数。
*
* @param millis
*            指定当前线程睡眠多久,以毫秒为单位
*/
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
*  解决Receiver not registered: android.widget.ViewFlipper问题,在android2.1,2.2上
*/
@Override
protected void onDetachedFromWindow () {
try {
super.onDetachedFromWindow();
}   catch (IllegalArgumentException e) {
stopFlipping();
}
}
/**
* 重写showNext()方法,用于实现图片自动切换时,图片的指示标也跟着切换
*/
@Override
public void showNext() {
super.showNext();
if(null != mImgBrowsingMark.getMarkView())
mImgBrowsingMark.getMarkView().setMark(getDisplayedChild());
}
/**
* 图片浏览指示标的回调接口
* @author sunday
*
*/
public interface IImageBrowsingMark {
public MarkView getMarkView();
}
}

MarkView.java类

package org.sunday.myflipper;
import org.sunday.myflipper.R;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
/**
* 图片浏览指示标
* @author sunday
*
*/
public class MarkView extends LinearLayout {
private ImageView[] mImageView;
private Context context;
public MarkView(Context context){
super(context);
this.context = context;
}
public MarkView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public void setMarkCount(int iCount) {
mImageView = new ImageView[iCount];
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
for (int i = 0; i < iCount; i++) {
ImageView image = new ImageView(context);
image.setImageResource(R.drawable.unselected_dot);
image.setLayoutParams(p);
mImageView[i] = image;
image.setId(i);
addView(image);
}
}
public void setMark(int position) {
for (int i = 0; i < mImageView.length; i++) {
if (i == position) {
mImageView[i].setImageResource(R.drawable.select_dot);
} else {
mImageView[i].setImageResource(R.drawable.unselected_dot);
}
}
}
}

DemoActivity.java类

package org.sunday.myflipper;
import org.sunday.myflipper.ImageBrowsingViewFlipper.IImageBrowsingMark;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
public class DemoActivity extends Activity implements IImageBrowsingMark  {
private MarkView markView;
private Drawable[] imgs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imgs = new Drawable[5];
imgs[0] =  getResources().getDrawable(R.drawable.img1);
imgs[1] =  getResources().getDrawable(R.drawable.img2);
imgs[2] =  getResources().getDrawable(R.drawable.img3);
imgs[3] =  getResources().getDrawable(R.drawable.img4);
imgs[4] =  getResources().getDrawable(R.drawable.img5);
setContentView(R.layout.demo);
ImageBrowsingViewFlipper ibvf = (ImageBrowsingViewFlipper) findViewById(R.id.viewflipper);
//设置图片浏览指示标接口
ibvf.setmImgBrowsingMark(this);
//设置图片
ibvf.setImgsDraw(imgs);
markView = (MarkView) findViewById(R.id.markView);
markView.setMarkCount(imgs.length);
//起始位置设置为0
markView.setMark(0);
// 向左滑动左侧进入的渐变效果(alpha 0.1  -> 1.0)
Animation lInAnim = AnimationUtils.loadAnimation(this, R.anim.push_left_in);
// 向左滑动右侧滑出的渐变效果(alpha 1.0  -> 0.1)
Animation lOutAnim = AnimationUtils.loadAnimation(this, R.anim.push_left_out);
ibvf.setInAnimation(lInAnim);
ibvf.setOutAnimation(lOutAnim);
// 设置自动播放功能
ibvf.setAutoStart(true);
if(ibvf.isAutoStart() && !ibvf.isFlipping()){
ibvf.startFlipping();
}
}
@Override
public MarkView getMarkView() {
return markView;
}
}

demo:http://download.csdn.net/detail/ff20081528/6843885

基于ViewFlipper实现图片浏览组件相关推荐

  1. tkinter类ppt的图片浏览组件

    tkinter类ppt的图片浏览组件 引言 框架 添加图片 显示图片 完整代码 效果 结语 引言 这里指的类ppt是指组件主体由图片选择框,原始图片显示框组成,木有自己的编辑功能. 框架 类似PPT, ...

  2. Vue图片浏览组件v-viewer简单应用

    v-viewer 用于图片浏览的Vue组件,支持旋转.缩放.翻转等操作,基于viewer.js. 安装 npm install v-viewer 使用 引用插件 main.js import View ...

  3. Vue - 图片浏览组件v-viewer

    1. 介绍和安装 v-viewer组件可以实现图片点击放大,缩小,旋转,切换等操作 在Vue项目中打开终端,npm引入v-viewer组件 npm install v-viewer --save 2. ...

  4. VUE图片裁剪组件,基于VueCropper

    VUE图片裁剪组件,基于VueCropper 搬砖的同志麻烦点个赞支持下 效果图 第一步安装vue-cropper插件 npm install vue-cropper 第二步创建组件,把下面的代码复制 ...

  5. vue h5 端实现富文本图片预览(基于 Vant UI 的 ImagePreview 组件)

    文章目录 vue h5 端实现富文本图片预览(基于 Vant UI 的 ImagePreview 组件) 预览效果 关键代码 使用案例 vue h5 端实现富文本图片预览(基于 Vant UI 的 I ...

  6. ssm java上传图片预览_基于JAVA的SSM图片浏览系统

    今天和一个朋友共同完成了一个图片浏览系统的设计与实现项目,我们在开发时选用的框架是SSM(MYECLIPSE)框架.我这个朋友知识有限,只会这个框架,哈哈,都是为了方便他.和往常一样选用简单又便捷的M ...

  7. 悟空活动中台 - 基于 WebP 的图片高性能加载方案

    本文首发于 vivo互联网技术 微信公众号  链接: https://mp.weixin.qq.com/s/rSpWorfNTajtqq_pd7H-nw 作者:悟空中台研发团队 一.背景 移动端网页的 ...

  8. 懒人图片浏览(image galleries,相册)功略——highslide篇

    网站特别社交类,经常用到图片浏览或相册集.对于FLASH不是很懂的我来说,只好寻求网络,还真让我找到两个相当易用,又酷炫的组件.基于脚本的highslide和基于FLASH的Simpleviewer. ...

  9. 【精心挑选】10款基于 jQuery 的图片360度旋转插件

    之前的文章向大家分享了实现网站功能的各种优秀的 jQuery 插件,今天这篇文章向大家推荐10款基于 jQuery 的图片360度旋转插件,同时还有非常详细的制作教程可以学习和参考.图片旋转展示是一种 ...

最新文章

  1. python绘制三维轨迹_Python学习(一) —— matplotlib绘制三维轨迹图
  2. Python实现有道翻译
  3. 大学最难的课是哪一门课?
  4. Spark数据分析及处理_ELT
  5. 201501006-构建之法:现代软件工程-阅读笔记
  6. iOS开发之UITableView自定义Header视图和自定义Footer视图
  7. ENVI5.3.1使用Landsat 8影像进行主成分分析实例操作
  8. junit搭配hamcrest使用
  9. mysql没有开启binlog能恢复数据吗_【数据库】一个 rm -rf 把公司整个数据库删没了
  10. Centos里tftp服务器的安装和配置
  11. 计算机mac地址的字节数,mac地址如何查询
  12. 1234变4321java_java:把1234成4321整数倒逆代码
  13. 检测到目标站点存在javascript框架库漏洞
  14. Word文档 回车符去除
  15. Android Studio出现Execution failed for task ‘:app:processDebugMainManifest
  16. 如何掌握程序语言(转自王垠Blog)
  17. 【ADB】adb命令的安装和使用(超级详细,命令大全)
  18. ssd的smt_探访固态硬盘工厂,揭秘 SSD 生产过程
  19. Maven3.6的下载和安装
  20. 纳兰容若 ----- 木兰花令 拟古决绝词

热门文章

  1. android设置加密步长,非稳态计算时Fluent 时间步长如何设置(转载)
  2. SQL Server数据库作业:连接查询
  3. 很不懂 对网络上面的话很不懂
  4. 微信小程序开发:自定义组件-behaviors
  5. dicom文件tag详解
  6. java计算机毕业设计乐勤网书店源码+系统+mysql数据库+lw文档
  7. 高清电脑壁纸桌面图片|到高图随心换高清图
  8. 搜云科技联合金色财经、荣宝斋 举办笔墨丹青2021艺术鉴赏会
  9. xfplay(先锋影音) v8.9.6 官方版​
  10. 信号归一化功率_线性调频(LFM)信号仿真分析