600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 基于ViewFlipper实现图片浏览组件

基于ViewFlipper实现图片浏览组件

时间:2023-04-24 13:53:07

相关推荐

基于ViewFlipper实现图片浏览组件

转载请说明出处:/ff1528

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

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

组件的功能

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

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

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

4,有图片浏览指示标;

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

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* -1-13* zhengchao1937@* 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() { @Overridepublic 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() {@Overridepublic 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);//当前显示的ImageViewImageView ivCurr = (ImageView) ImageBrowsingViewFlipper.this.getCurrentView();currViewPosition = ImageBrowsingViewFlipper.this.getDisplayedChild();//下一个ImageViewImageView ivNext = getNextView(currViewPosition);//上一个ImageViewImageView 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> {@Overrideprotected 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;}@Overrideprotected void onProgressUpdate(Integer... xDistance) {int xNext = - vfWidth + xDistance[0];Log.e(TAG, "xNext = " + xNext);ivCurr.scrollTo(xDistance[0], 0);ivNext.scrollTo(xNext, 0);}@Overrideprotected 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> {@Overrideprotected 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;}@Overrideprotected void onProgressUpdate(Integer... xDistance) {int xLast = vfWidth - xDistance[0];Log.e(TAG, "xLast = " + xLast);ivCurr.scrollTo(-xDistance[0], 0);ivLast.scrollTo(xLast, 0);}@Overrideprotected 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上*/@Overrideprotected void onDetachedFromWindow () {try {super.onDetachedFromWindow();}catch (IllegalArgumentException e) {stopFlipping();}}/*** 重写showNext()方法,用于实现图片自动切换时,图片的指示标也跟着切换*/@Overridepublic 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;@Overrideprotected 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);//起始位置设置为0markView.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();}}@Overridepublic MarkView getMarkView() {return markView;}}

demo:/detail/ff1528/6843885

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。