imageswitch的自动切换的一个工具类

2024-01-12 03:18

本文主要是介绍imageswitch的自动切换的一个工具类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

主要代码

public class ImageSwitcher extends ViewGroup {

    
    private String TAG = ImageSwitcher.class.getSimpleName();
    private static final int SNAP_VELOCITY = 300;

    private Scroller scroller;
    
    private VelocityTracker mVelocityTracker;
    
    private int mTouchSlop;

    private float mMotionX;

    private int mImageWidth;
    
    private int imageCount;

    private int mIndex;

    private int mImageHeight;
    
    private int[] imageItems;
    
    private boolean forceToRelayout;
    
    private int mTouchState = TOUCH_STATE_REST;
    
    private static final int TOUCH_STATE_REST = 0;
    private static final int TOUCH_STATE_SCROLLING = 1;
    
    private static final int AUTO_MSG = 0;
    
    private static final int START_MSG =2;
    
    private static final int HANDLE_MSG = 1;
    
    private static final long PHOTO_CHANGE_TIME = 4000;
    
    
    private  Handler mHandler = new Handler(){ //处理图片自动或者手动滚动操作
        
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case AUTO_MSG:
                scrollToNext();
                mHandler.sendEmptyMessageDelayed(AUTO_MSG, PHOTO_CHANGE_TIME);
                break;
            case START_MSG:
                mHandler.sendEmptyMessageDelayed(AUTO_MSG, PHOTO_CHANGE_TIME);
                break;
            case HANDLE_MSG:
                mHandler.removeMessages(AUTO_MSG);
                mHandler.sendEmptyMessageDelayed(AUTO_MSG, PHOTO_CHANGE_TIME);
            default:
                break;
            }
        }
    };

    /**
     * 表示滚动到下一张图片这个动作
     */
    private static final int SCROLL_NEXT = 0;
    /**
     * 表示滚动到上一张图片这个动作
     */
    private static final int SCROLL_PREVIOUS = 1;
    
    private static final int SCROLL_BACK = 2;
    
    
    public ImageSwitcher(Context context, AttributeSet attrs) {
        super(context, attrs);
        scroller = new Scroller(context);
        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    }
    
    /**
     * 当View被添加到Window容器的时候才开始执行:生命周期依次先后 onMeasure > onLayout > onDraw >onAttachedToWindow
     */
    @Override
    protected void onAttachedToWindow(){
        super.onAttachedToWindow();
        mHandler.sendEmptyMessage(START_MSG); //发送消息让图片自动开始滚动
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(changed || forceToRelayout){
            imageCount = getChildCount();
            mImageWidth = getMeasuredWidth();
            mImageHeight = getMeasuredHeight();
            int marginLeft = 0;
            scroller.abortAnimation(); //设置scroller为滚动状态
            this.scrollTo(0, 0); //每次重新布局时候,重置滚动初始位置
            int[] items = { getIndexForItem(1), getIndexForItem(2),
                    getIndexForItem(3), getIndexForItem(4),
                    getIndexForItem(5) };
            imageItems = items;
            for (int i = 0; i < items.length; i++) {
                ImageView childView = (ImageView)getChildAt(items[i]);
                childView.layout(marginLeft, 0, marginLeft
                        + mImageWidth , mImageHeight);
                marginLeft = marginLeft + mImageWidth;
            }
            refreshImageView();
            forceToRelayout = false;
        }
    }
    
    private void refreshImageView(){
        for (int i = 0; i < imageItems.length; i++) {
            ImageView childView = (ImageView)getChildAt(imageItems[i]);
            childView.invalidate();
        }
    }
    

    private int getIndexForItem(int item) {
        int index = -1;
        index = mIndex + item - 3;
        while (index < 0) {
            index = index + imageCount;
        }
        while (index > imageCount - 1) {
            index = index - imageCount;
        }
        return index;
    }
    
    @Override
    public boolean  onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if ((action == MotionEvent.ACTION_MOVE)
                && (mTouchState != TOUCH_STATE_REST)) {
            return true;        
        }
        float xLoc = ev.getX();
        switch(action){
        case MotionEvent.ACTION_DOWN:
            mMotionX = xLoc;
            mTouchState = TOUCH_STATE_REST;
            Log.e(TAG, "onInterceptTouchEvent ACTION_DOWN");  
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(TAG, "onInterceptTouchEvent ACTION_MOVE");  
             int xDif = (int)Math.abs(mMotionX - xLoc);
             if(xDif > mTouchSlop){  //当我们的水平距离滚动达到我们滚动的最小距离,开始拦截ViewGroup的事件给子控件分发
                 mTouchState = TOUCH_STATE_SCROLLING;
             }
            break;
        case MotionEvent.ACTION_UP:
            Log.e(TAG, "onInterceptTouchEvent ACTION_UP");  
            mTouchState = TOUCH_STATE_REST;
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(TAG, "onInterceptTouchEvent ACTION_CANCEL");
            mTouchState = TOUCH_STATE_REST;
            break;
        default:
            Log.e(TAG, "onInterceptTouchEvent DEFAULT");
            mTouchState = TOUCH_STATE_REST;
            break;
        }
        return mTouchState != TOUCH_STATE_REST;
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(scroller.isFinished()){ //scroller还没有开始或者已经完成,以下代码在手指滑动的时候才开始执行
            if (mVelocityTracker == null) {
                mVelocityTracker = VelocityTracker.obtain();
            }
            mVelocityTracker.addMovement(event);
            int action = event.getAction();
            float x = event.getX();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                // 记录按下时的横坐标
                mMotionX = x;
            case MotionEvent.ACTION_MOVE:
                int disX = (int)(mMotionX - x);
                mMotionX = x;
                scrollBy(disX, 0);
                break;
            case MotionEvent.ACTION_UP:
                mVelocityTracker.computeCurrentVelocity(1000);
                int velocityX = (int) mVelocityTracker.getXVelocity();
                if (judeScrollToNext(velocityX)) {
                    // 下一张图
                    scrollToNext();
                } else if (judeScrollToPrevious(velocityX)) {
                    //上一张图
                    scrollToPrevious();
                } else {
                    // 当前图片
                    scrollBack();
                }
                if (mVelocityTracker != null) {
                    mVelocityTracker.recycle();
                    mVelocityTracker = null;
                }
                mHandler.sendEmptyMessageDelayed(HANDLE_MSG, PHOTO_CHANGE_TIME);
                return true;
            }
        }
        return false;
    }
    

    private void scrollBack() {
        if (scroller.isFinished()) {
            beginScroll(getScrollX(), 0, -getScrollX(), 0,SCROLL_BACK);
        }
    }

    private void scrollToPrevious() {
        if(scroller.isFinished()){
            setImageSwitchIndex(SCROLL_PREVIOUS);
            int disX = -mImageWidth - getScrollX();
            beginScroll(getScrollX(), 0, disX, 0,SCROLL_PREVIOUS);
        }
    }

    private void scrollToNext() {
        if (scroller.isFinished()) {
            setImageSwitchIndex(SCROLL_NEXT);
            int disX = mImageWidth - getScrollX();
            beginScroll(getScrollX(), 0, disX, 0,SCROLL_NEXT);
        }
    }
    
    /**
     * 图片开始滑动
     */
    private void beginScroll(int startX, int startY, int dx, int dy,
            final int action) {
        int duration = (int) (700f / mImageWidth * Math.abs(dx));
        scroller.startScroll(startX, startY, dx, dy, duration);
        invalidate();
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (action == SCROLL_NEXT || action == SCROLL_PREVIOUS) {
                    forceToRelayout = true;
                    requestLayout();
                }
            }
        }, duration);
    }

    private void setImageSwitchIndex(int action) {
        if(action == SCROLL_NEXT){
            if(mIndex < imageCount){
                mIndex++;
            }else{
                mIndex = 0;
            }
        }else if(action == SCROLL_PREVIOUS){
            if(mIndex > 0){
                mIndex--;
            }else{
                mIndex = imageCount -1;
            }
        }
        
    }

    /**
     * 判断时候滑向前一个
     * @param velocityX
     * @return
     */
    private boolean judeScrollToPrevious(int velocityX) {
        return velocityX > SNAP_VELOCITY || getScrollX() < -mImageWidth / 2;
    }

    /**
     * 判断时候滑向后一个
     * @param velocityX
     * @return
     */
    private boolean judeScrollToNext(int velocityX) {
        return velocityX < -SNAP_VELOCITY|| getScrollX() > mImageWidth / 2;
    }
    
    @Override
    public void computeScroll() {    
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            //刷新View 否则效果可能有误差
            postInvalidate();
        }
    }
    
}



布局


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
     <com.zhanglei.imageswitcher.ImageSwitcher
        android:id="@+id/image_switch_view"
        android:layout_width="match_parent"
        android:layout_height="200dp" >
        <ImageView
            android:id="@+id/image1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:clickable="true"
            android:src="@drawable/item01"/>
        <ImageView
            android:id="@+id/image2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:clickable="true"
            android:src="@drawable/item02"/>
        <ImageView
            android:id="@+id/image3"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:clickable="true"
            android:src="@drawable/item03"/>
        <ImageView
            android:id="@+id/image4"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:clickable="true"
            android:src="@drawable/item04"/>
         <ImageView
            android:id="@+id/image5"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:clickable="true"
            android:src="@drawable/item05"/>
    </com.zhanglei.imageswitcher.ImageSwitcher>


</RelativeLayout>
效果就不展示了,因为我不会录像,嘎嘎

拿来就可以用哦


这篇关于imageswitch的自动切换的一个工具类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/596634

相关文章

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

linux部署NFS和autofs自动挂载实现过程

《linux部署NFS和autofs自动挂载实现过程》文章介绍了NFS(网络文件系统)和Autofs的原理与配置,NFS通过RPC实现跨系统文件共享,需配置/etc/exports和nfs.conf,... 目录(一)NFS1. 什么是NFS2.NFS守护进程3.RPC服务4. 原理5. 部署5.1安装NF

基于Go语言开发一个 IP 归属地查询接口工具

《基于Go语言开发一个IP归属地查询接口工具》在日常开发中,IP地址归属地查询是一个常见需求,本文将带大家使用Go语言快速开发一个IP归属地查询接口服务,有需要的小伙伴可以了解下... 目录功能目标技术栈项目结构核心代码(main.go)使用方法扩展功能总结在日常开发中,IP 地址归属地查询是一个常见需求:

使用python制作一款文件粉碎工具

《使用python制作一款文件粉碎工具》这篇文章主要为大家详细介绍了如何使用python制作一款文件粉碎工具,能够有效粉碎密码文件和机密Excel表格等,感兴趣的小伙伴可以了解一下... 文件粉碎工具:适用于粉碎密码文件和机密的escel表格等等,主要作用就是防止 别人用数据恢复大师把你刚删除的机密的文件恢

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

MySQL慢查询工具的使用小结

《MySQL慢查询工具的使用小结》使用MySQL的慢查询工具可以帮助开发者识别和优化性能不佳的SQL查询,本文就来介绍一下MySQL的慢查询工具,具有一定的参考价值,感兴趣的可以了解一下... 目录一、启用慢查询日志1.1 编辑mysql配置文件1.2 重启MySQL服务二、配置动态参数(可选)三、分析慢查