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

相关文章

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

IDEA中新建/切换Git分支的实现步骤

《IDEA中新建/切换Git分支的实现步骤》本文主要介绍了IDEA中新建/切换Git分支的实现步骤,通过菜单创建新分支并选择是否切换,创建后在Git详情或右键Checkout中切换分支,感兴趣的可以了... 前提:项目已被Git托管1、点击上方栏Git->NewBrancjsh...2、输入新的分支的

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

浏览器插件cursor实现自动注册、续杯的详细过程

《浏览器插件cursor实现自动注册、续杯的详细过程》Cursor简易注册助手脚本通过自动化邮箱填写和验证码获取流程,大大简化了Cursor的注册过程,它不仅提高了注册效率,还通过友好的用户界面和详细... 目录前言功能概述使用方法安装脚本使用流程邮箱输入页面验证码页面实战演示技术实现核心功能实现1. 随机

sqlite3 命令行工具使用指南

《sqlite3命令行工具使用指南》本文系统介绍sqlite3CLI的启动、数据库操作、元数据查询、数据导入导出及输出格式化命令,涵盖文件管理、备份恢复、性能统计等实用功能,并说明命令分类、SQL语... 目录一、启动与退出二、数据库与文件操作三、元数据查询四、数据操作与导入导出五、查询输出格式化六、实用功

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

SQLite3命令行工具最佳实践指南

《SQLite3命令行工具最佳实践指南》SQLite3是轻量级嵌入式数据库,无需服务器支持,具备ACID事务与跨平台特性,适用于小型项目和学习,sqlite3.exe作为命令行工具,支持SQL执行、数... 目录1. SQLite3简介和特点2. sqlite3.exe使用概述2.1 sqlite3.exe

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2