显示Gif菜单

news2024/9/23 19:25:08

需要

最近研究在底部菜单中加入gif播放。这样显得高级一些。研究了一些技术方案,现在写篇博客,沉淀一下。

效果

在这里插入图片描述

实现

通过Glide实现。虽然android官方有AnimatedImageDrawable 但是只支持API28以上,也就是android9.0以上的手机。兼容性太差。

写了一个工具类,可以根据传入的两个drawable的id值。自动生成一个StateListDrawable 。在view被选中的时候,显示相关图片。如果相关图片是gif就播放一次。

难点在于怎么播放一次。
我的方法是先stop,再调用startFromFirstFrame

还有就是怎么监听状态的改变,在onStateChange添加记录即可。

关于StateListDrawable 手动调用addState时要注意。空的状态数组表示默认状态。一定要最后一个添加。如果第一个添加。其他状态都无法匹配,将始终显示默认状态。

这个工具类依赖glide,需要引入依赖

    implementation 'com.github.bumptech.glide:glide:4.15.1'

工具

/**
 * <pre>
 * Created by zhuguohui
 * Date: 2023/7/7
 * Time: 14:54
 * Desc:
 * </pre>
 */
public class GifUtil {

    public static void setDrawable(ImageView imageView,int normalId, int selectedId) {


        GIfStateListDrawable listDrawable = new GIfStateListDrawable();
        addState(imageView, new int[]{android.R.attr.state_selected}, selectedId, listDrawable, () -> {
            addState(imageView, new int[]{}, normalId, listDrawable, () -> {
                imageView.setImageDrawable(listDrawable);
            });
        });
    }

    private interface CallBack {
        void call();
    }

    private static void addState(ImageView imageView, int[] states, int resId, StateListDrawable listDrawable, CallBack callBack) {
        Glide.with(imageView)
                .asDrawable()
                .load(resId)
                .into(new CustomTarget<Drawable>() {
                    @Override
                    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                        listDrawable.addState(states, resource);
                        callBack.call();
                    }

                    @Override
                    public void onLoadCleared(@Nullable Drawable placeholder) {

                    }
                });
    }


    public static class GIfStateListDrawable extends StateListDrawable {

        private  boolean stateChange=false;
        @Override
        protected boolean onStateChange(int[] stateSet) {
            boolean change=super.onStateChange(stateSet);
            if(change){
                stateChange=true;
            }
            return change;
        }

        @Override
        public void draw(Canvas canvas) {
            super.draw(canvas);
            if(stateChange) {
                //确保只播放一次gif
                stateChange=false;
                Drawable current = getCurrent();
                if (current instanceof GifDrawable) {
                    GifDrawable gifDrawable = (GifDrawable) current;
                    gifDrawable.setLoopCount(1);
                    gifDrawable.stop();
                    gifDrawable.startFromFirstFrame();
                }
            }
        }
    }

}

使用

demo

使用很简单,传入两个drawable就行了。更过修改view的selected状态来自动播放gif

public class MainActivity extends AppCompatActivity {
    ImageView iv1,iv2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv1=findViewById(R.id.iv_1);
        iv2=findViewById(R.id.iv_2);
        GifUtil.setDrawable(iv1,R.drawable.city_normal,R.drawable.city_selected);
        GifUtil.setDrawable(iv2,R.drawable.home_normal,R.drawable.home_selected);


        iv1.setOnClickListener(v->{
            iv1.setSelected(true);
            iv2.setSelected(false);
        });

        iv2.setOnClickListener(v->{
            iv2.setSelected(true);
            iv1.setSelected(false);
        });
    }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎样做好客户自助服务?

在当前高速发展的信息化时代&#xff0c;人们已经习惯了即时满足的方式。对于品牌来说&#xff0c;当客户遇到问题时&#xff0c;他们希望能够获得即时细致的解答。如果客户需要等待很长时间才能获取答案&#xff0c;他们的满意度就会降低。因此&#xff0c;企业是否提供客户自…

flutter开发实战-自定义Switch开关控件Widget

flutter开发实战-自定义Switch开关控件 在flutter中实现自定义Switch&#xff0c;主要实现类似IOS的UISwitch样式的开关控件 一、效果图 二、实现Switch开关的Widget 实现自定义Switch的Widget&#xff0c;主要实现交织动画。 交织动画 有些时候我们可能会需要一些复杂的动画…

apache 安装配置 基础篇(二)

在使用Apache时&#xff0c;配置虚拟主机可以允许一个单一的Apache服务器提供不同的网站、域名或IP地址。 Apache虚拟主机的一个重要作用是更好的网站管理能力。当一个虚拟主机被创建时&#xff0c;您可以轻松地分配不同的域名和IP地址&#xff0c;设置不同的目录、文件和权限…

【电影推荐系统】基于 ALS 的协同过滤推荐算法

目录 目的 用户电影推荐矩阵主要思路如下 1 UserId 和 MovieID 做笛卡尔积&#xff0c;产生&#xff08;uid&#xff0c;mid&#xff09;的元组 2 通过模型预测&#xff08;uid&#xff0c;mid&#xff09;的元组。 3 将预测结果通过预测分值进行排序。 4 返回分值最大的 …

js debugger的两种方式

第一种&#xff1a;在js代码中加上debugger class ReactiveEffect {constructor(fn, scheduler) {this.fn fn;this.scheduler scheduler;this.active true;this.deps [];console.log("创建 ReactiveEffect 对象");}run() {debugger; console.log("run…

Spring高手之路8——Spring Bean模块装配的艺术:@Import详解

文章目录 1. Spring手动装配基础2. Spring框架中的模块装配2.1 Import注解简单使用 3. Import模块装配的四种方式3.1 Import注解的功能介绍3.2 导入普通类与自定义注解的使用3.3 导入配置类的策略3.4 使用ImportSelector进行选择性装配3.5 使用ImportBeanDefinitionRegistrar进…

指针进阶详解

目录 指针基本概念 1.字符指针 2.指针数组 3.数组指针 对数组名的理解 小结 指针基本概念 在初阶指针中我们了解到一些指针的基本概念: 1.指针就是个变量&#xff0c;用来存放地址&#xff0c;地址唯一标识一块内存 2.指针的大小是固定的4/8个字节&#xff08;32位/64位平台&…

详解c++---哈希封装

目录标题 哈希桶的代码哈希桶的修改迭代器的实现const迭代器 哈希桶的代码 通过前面的学习大家应该能够很容易的写出下面的代码&#xff1a; #pragma once #include<iostream> #include<vector> using namespace std; template<class K,class V> struct Ha…

2023年互联网行业研究报告

第一章 行业概况 互联网行业是一个广泛的领域&#xff0c;包括所有利用互联网技术进行商业活动的企业和组织。这个行业的核心是互联网&#xff0c;一个全球性的网络&#xff0c;连接着数以亿计的计算设备和用户&#xff0c;使他们可以共享信息、资源和服务。 互联网行业包括网…

apache 安装配置 基础篇(-)

download 地址 apache下载 ApacheHaus是免安装的&#xff0c; 然后解压上面的文件&#xff0c;把里面 因apache 默认端口是80&#xff0c;如果这个端口被占用&#xff0c;apache服务是启动不起来的 netstat -ano|findstr 80 apache 修改端口号 创建apache服务 在apa…

ESP32-H2 固件烧录需满足的硬件环境整理

ESP32-H2 默认通过 UART0 &#xff08;即 TXD&#xff08;GPIO24&#xff09;和 RXD&#xff08;GPIO23&#xff09;&#xff09;下载固件。 Windows 下可使用 Flash download tool 工具来下载编译后的 bin 文件&#xff1b; 运行 flash_download_tool.exe 的文件 选择开发…

SkyEye处理器仿真系列:龙芯2K1000处理器

​SkyEye简介&#xff1a; 天目全数字实时仿真软件SkyEye作为基于可视化建模的硬件行为级仿真平台&#xff0c;能够为嵌入式软件提供虚拟化运行环境&#xff0c;开发、测试人员可在该虚拟运行环境上进行软件开发、软件测试和软件验证活动。小到芯片&#xff0c;大到系统&#…

win10 DBeaver (升级)下载、安装、彻底卸载

DBeaver &#xff08;升级&#xff09;下载及安装 一、DBeaver 下载二、安装三、DBeaver 的基本使用 - mysql连接四、DBeaver 彻底卸载 DBeaver是一种通用数据库管理工具&#xff0c;适用于需要以专业方式使用数据的每个人&#xff1b;适用于开发人员&#xff0c;数据库管理员&…

苹果笔买原装的还是随便买?便宜好用的手写笔推荐

自从ipad和其他的平板电脑都搭配上了电容笔以后&#xff0c;电容笔很好地取代了我们的手指&#xff0c;书写的效率就大大提升了&#xff0c;但由于苹果原装电容笔的价格不够人性化&#xff0c;一直高居不下给普通人带来了很大的负担&#xff0c;特别是对于学生们来说&#xff0…

QT DAY1

做一个窗口界面 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);//设置窗口标题、图标this->setWindowTitle("Fly_Chat")…

6、Flume安装部署

按照采集通道规划&#xff0c;需在hadoop102&#xff0c;hadoop103&#xff0c;hadoop104三台节点分别部署一个Flume。可参照以下步骤先在hadoop102安装&#xff0c;然后再进行分发。 1、Flume入门 1.1、 Flume安装部署 1.1.1、 安装地址 &#xff08;1&#xff09; Flume官…

全网最牛,Web自动化测试Selenium八大元素定位实战(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 安装Selenium和下…

BFT 最前线|OpenAI暂时下线ChatGPT”浏览“功能;Stability AI CEO:5年内,人类程序员将不复存在

原创 | 文 BFT机器人 AI视界 TECHNOLOGY NEWS 01 Open AI暂时下线ChatGPT“浏览”功能 日前OpenAI方面宣布&#xff0c;面向ChatGPT Plus用户的"浏览"功能会在某些情况下出现故障&#xff0c;因此已于7月3日暂时禁用了这一功能。该功能是为了提高ChatGPT的搜索体验…

威胁检测和取证日志分析

在网络中&#xff0c;威胁是指可能影响其平稳运行的恶意元素。因此&#xff0c;对于任何希望搁置任何财政损失或生产力下降机会的组织来说&#xff0c;威胁检测都是必要的。为了先发制人地阻止来自各种来源的任何此类攻击&#xff0c;需要有效的威胁检测情报。 威胁检测可以是…

mmap函数

参考 https://blog.csdn.net/bhniunan/article/details/104105153void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);参数 addr&#xff1a;出参&#xff0c; 指定映射的起始地址&#xff0c;通常设为NULL&#xff0c;由内核来分配 len&#x…