Android使用自定义属性实现图片自动播放滚动的功能
作者:guolin 发布时间:2023-04-13 18:51:49
大家好,记得上次我带着大家一起实现了一个类似与淘宝客户端中带有的图片滚动播放器的效果,但是在做完了之后,发现忘了加入图片自动播放的功能(或许是我有意忘记加的.....),结果图片只能通过手指滑动来播放。于是今天我将再次带领大家,添加上之前遗漏的功能,让我们的图片播放器更加完善。
这次的程序开发将完全基于上一次的代码,如果有朋友还未看过上篇文章,请先阅读Android实现图片滚动和页签控件功能的实现代码。
既然是要加入自动播放的功能,那么就有一个非常重要的问题需要考虑。如果当前已经滚动到了最后一张图片,应该怎么办?由于我们目前的实现方案是,所有的图片都按照布局文件里面定义的顺序横向排列,然后通过偏移第一个图片的leftMargin,来决定显示哪一张图片。因此当图片滚动在最后一张时,我们可以让程序迅速地回滚到第一张图片,然后从头开始滚动。这种效果和淘宝客户端是有一定差异的(淘宝并没有回滚机制,而是很自然地由最后一张图片滚动到第一张图片),我也研究过淘宝图片滚动器的实现方法,并不难实现。但是由于我们是基于上次的代码进行开发的,方案上无法实现和淘宝客户端一样的效果,因此这里也就不追求和它完全一致了,各有风格也挺好的。
好了,现在开始实现功能,首先是打开SlidingSwitcherView,在里面加入一个新的AsyncTask,专门用于回滚到第一张图片:
class ScrollToFirstItemTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
int leftMargin = firstItemParams.leftMargin;
while (true) {
leftMargin = leftMargin + speed[0];
// 当leftMargin大于0时,说明已经滚动到了第一个元素,跳出循环
if (leftMargin > 0) {
leftMargin = 0;
break;
}
publishProgress(leftMargin);
sleep(20);
}
return leftMargin;
}
@Override
protected void onProgressUpdate(Integer... leftMargin) {
firstItemParams.leftMargin = leftMargin[0];
firstItem.setLayoutParams(firstItemParams);
}
@Override
protected void onPostExecute(Integer leftMargin) {
firstItemParams.leftMargin = leftMargin;
firstItem.setLayoutParams(firstItemParams);
}
}
然后在SlidingSwitcherView里面加入一个新的方法:
/**
* 滚动到第一个元素。
*/
public void scrollToFirstItem() {
new ScrollToFirstItemTask().execute(20 * itemsCount);
}
这个方法非常简单,就是启动了我们新增的ScrollToFirstItemTask,滚动速度设定为20 * itemsCount,这样当我们需要滚动的图片数量越多,回滚速度就会越快。定义好这个方法后,只要在任意地方调用scrollToFirstItem这个方法,就可以立刻从当前图片回滚到第一张图片了。
OK,然后我们要定义一个方法用于启动自动播放功能。仍然是在SlidingSwitcherView中新增如下代码:
/**
* 用于在定时器当中操作UI界面。
*/
private Handler handler = new Handler();
/**
* 开启图片自动播放功能,当滚动到最后一张图片的时候,会自动回滚到第一张图片。
*/
public void startAutoPlay() {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if (currentItemIndex == itemsCount - 1) {
currentItemIndex = 0;
handler.post(new Runnable() {
@Override
public void run() {
scrollToFirstItem();
refreshDotsLayout();
}
});
} else {
currentItemIndex++;
handler.post(new Runnable() {
@Override
public void run() {
scrollToNext();
refreshDotsLayout();
}
});
}
}
}, 3000, 3000);
}
我们可以看到,这个方法里启用了一个定时器,每隔三秒就会执行一次。然后在定时器的执行逻辑里面进行判断当前图片是否是最后一张,如果不是最后一张就滚动到下一张图片,如果是最后一张就回滚到第一张图片。其中需要注意,定时器中的代码是在子线程中运行的,而滚动图片操作和更新页签操作都是UI操作,因此需要放到Handler中去执行。
之后只要在Activity创建的时候去调用SlidingSwitcherView的startAutoPlay方法,自动播放功能就实现了!!
结束了?Naive!! 如果就这么结束了,怎么对得起大家的期待,如此简单的功能还要用一篇文章来讲简直是弱爆了。
接下来才是今天的重点,我们要使用自定义属性来启用自动播放功能,这样才能让你更加接近高手,才能让你更加玩转Android。
那我们继续,在res/values目录下新建一个attrs.xml文件,里面加入代码:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<attr name="auto_play" forMymat="boolean" />
<declare-styleable name="SlidingSwitcherView">
<attr name="auto_play" />
</declare-styleable>
</resources>
其中,auto_play是我们将要使用的属性名,格式是布尔型。SlidingSwitcherView这个值可以随意,主要在代码中需要引用相应的id。
然后重写SlidingSwitcherView的构造函数,在里面加入从布局文件中获取自定义属性的代码:
public SlidingSwitcherView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SlidingSwitcherView);
boolean isAutoPlay = a.getBoolean(R.styleable.SlidingSwitcherView_auto_play, false);
if (isAutoPlay) {
startAutoPlay();
}
a.recycle();
}
可以看到,我们在构造函数中去获取auto_play的值,如果为true,就调用startAutoPlay方法,从而启用了自动播放的功能。
接下来就是见证奇迹的时刻!让我们打开activity_main.xml,在里面加入两行关键性代码。在最外层的LinearLayout加入在我们自定义的com.example.viewswitcher.SlidingSwitcherView加入myattr:auto_play="true"。完整XML代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:myattr="http://schemas.android.com/apk/res/com.example.viewswitcher"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<com.example.viewswitcher.SlidingSwitcherView
android:id="@+id/slidingLayout"
myattr:auto_play="true"
android:layout_width="fill_parent"
android:layout_height="100dip" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/image1" />
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/image2" />
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/image3" />
<Button
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/image4" />
</LinearLayout>
<LinearLayout
android:layout_width="60dip"
android:layout_height="20dip"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="15dip"
android:orientation="horizontal" >
</LinearLayout>
</com.example.viewswitcher.SlidingSwitcherView>
</LinearLayout>
也就是说,我们只需要通过设定myattr:auto_play是等于true还是false,就可以决定是否启用自动播放功能,非常简单方便。
好了,今天的讲解到此结束,有疑问的朋友请在下面留言。
源码下载,请点击这里
来源:https://blog.csdn.net/guolin_blog/article/details/8796877
猜你喜欢
- 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。步骤为:1.从数
- 本文实例讲述了Java实现的校验银行卡功能。分享给大家供大家参考,具体如下:步骤:首先区分借记卡和信用卡,然后就是校验卡号,最后根据银联Bi
- 一、C#对XML格式数据的解析1、用XMLDocument来解析XmlDocument xmlDocument = new XmlDocum
- 对于某些程序,我们只允许它使用某些特定端口、网络类型或者特定IP类型等信息。这时候,需要使用到防火墙里面的“高级设置”,创建某些特定的入站或
- 本文实例讲述了C#针对xml的基本操作及保存配置文件应用,分享给大家供大家参考。具体方法如下:引言:这里首先介绍了xml的基本操作,后面写了
- 本文实例讲述了java基于AES对称加密算法实现的加密与解密功能。分享给大家供大家参考,具体如下:package com.soufun.co
- 如下所示:class B {public B() { super(); System.out.println(&qu
- 一、Mybatis一对多分解式查询分解式查询就是将一条Sql语句拆分成多条在MyBatis多表查询中,使用连接查询时一个Sql语句就可以查询
- 在C#的List集合操作中,有时候需要查找到List集合中的最大值,此时可以使用List集合的扩展方法Max方法,Max方法有2种形式,一种
- 在windows环境下进行的测试,前提条件,windows上需要先安装openssl。配置环境变量,查看版本:import java.io.
- 读语句: String str = ConfigurationManager.AppSettings["DemoKey"
- 一、编译步骤解压下载的GDAL源程序,并在命令行中切换到解压目录。tar -xzvf gdal-2.1.3.tar.gzcd gdal-2.
- 介绍和使用场景1)什么是消息一个事件,需要广播或者单独传递给某个接口2)为什么使用这个配置更新了,但是其他系统不知道是否更新SpringCl
- 初始化项目打开IntelliJ IDEA,我的版本是Version 2018.1.4。点击Create New Project。在左侧的列表
- 前言taptap-developer是一个spring boot框架驱动的纯Grpc服务,所以,只用了四步,移除了web和spring cl
- 之前自己从来没有做过发送邮箱的功能,前段时间项目需要,在找了很多帖子之后,终于实现了。之后有整理了一下,写了一个类。直接给类传递信息,就可以
- 一、系统自动抛出异常当程序语句出现一些逻辑错误、主义错误或者类型转换错误时,系统会自动抛出异常例一public static void ma
- 我们很容易能想到,可以用递归来实现汉诺塔游戏。因为要将n(n>1)个盘子从“源”柱子移到“目标”柱子,我们要先把n-1个盘子从“源”柱
- 前言今天有一个需求,把之前的判断逻辑进行修改,之前我是用大于(>)小于(<)进行对比的,但是今天让改成大于等于(>=)和小
- java 使用异常的好处总结一、分析Java异常处理机制确实比较慢,这个“比较慢”是相对于诸如String、Integer等对象来说,单单从