Android用ViewAnimator写一个简单的控件轮播效果
Posted wodongx123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android用ViewAnimator写一个简单的控件轮播效果相关的知识,希望对你有一定的参考价值。
控件轮播
前言
因为项目的需求,需要实现一个文字滚动轮播的功能,图我暂时找不到,脑补一下就是文字会往上滚动,然后显示另一段文字。且有多段这样的文字需要按顺序播放的这样。
android内部自带一个ViewAnimator控件,可以实现这种控件切换的功能。
虽然本文的内容只是一个TextView的轮播功能,但是举一反三可以做到任何复杂控件的轮播
1. ViewAnimator
<ViewAnimator
android:id="@+id/va"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是第一个TextView"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我是第二个TextView"/>
</ViewAnimator>
简单设置一下ViewAnimator,这是一个ViewGroup,所以直接在内部增加子控件就可以。
而ViewAnimator的调用方式也很简单,只要调用showNext()方法,就会自动显示下一个控件。
public class MainActivity extends AppCompatActivity
ViewAnimator viewAnimator;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewAnimator = findViewById(R.id.va);
viewAnimator.showNext();
运行,显示的是 “我是第二个TextView”。
2. 动态添加View
在确认了ViewAnimator的切换功能之后,接下来就是实现一个轮播效果,假设我们有一个String类型的数组,我们需要让list内的内容一直轮播。
那我们就需要和数组大小同等数量的控件,这个无法在xml中设置,可以参考我这篇文章
Android如何在运行时动态添加View_wodongx123的博客-CSDN博客
https://blog.csdn.net/qq_41872247/article/details/114401569
总之,我们先清除ViewAnimator内部的两个TextView,然后全部采用代码添加控件的方式。
public class MainActivity extends AppCompatActivity
ViewAnimator viewAnimator;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewAnimator = findViewById(R.id.va);
initView();
/**
* 初始化ViewAnimator内部的控件
*/
private void initView()
for(int i=0; i<list.length; i++)
TextView textView = new TextView(this);
textView.setText(list[i]);
viewAnimator.addView(textView);
3. CountDownTimer
添加了足够数量的控件之后,就是要实现轮播的功能了,我们不用Timer这个类,因为在Android中我们不能用子线程操作UI。而Android自己用Timer+Handler封装了一个CountdownTimer类,就用他来实现定时切换的功能。
public class MainActivity extends AppCompatActivity
private static final long INTERVAL = 2000;
private static final long FUTURE = INTERVAL * 2;
//......省略刚才出现过的代码......
@Override
protected void onCreate(Bundle savedInstanceState)
//......省略上面出现过的代码......
initTimer();
private void initTimer()
// 构造方法两个参数,第一个参数表示多久结束timer,即间隔多久后调用onfinish,调用后timer结束。
// 第二个参数表示间隔多久调用一次onTick,就是间隔方法,会反复调用
timer = new CountDownTimer(FUTURE, INTERVAL)
@Override
public void onTick(long millisUntilFinished)
viewAnimator.showNext();
@Override
public void onFinish()
// 在结束后立刻重新启动
timer.start();
;
timer.start();
@Override
protected void onDestroy()
super.onDestroy();
if(timer != null)
timer.cancel();
timer = null;
4. 切换动画
最后加上切换用的动画,就简单的用补间动画就好。(在res中创建anim包,然后新建两个xml文件)
R.anim.in
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="-100"
android:toYDelta="0"
android:duration="500"/>
</set>
R.anim.out
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="0"
android:toYDelta="100"
android:duration="500"/>
</set>
用代码设置完,这样ViewAnimator所有的内容就结束了。
viewAnimator.setInAnimation(this, R.anim.anim_in);
viewAnimator.setOutAnimation(this, R.anim.anim_out);
5. 优化
当我们有数十甚至数百个文本需要轮播的时候,这个时候就不能创建那么多控件来进行轮流播放了,对内存的消耗太大。
我的建议是,只创建两个View,当播放第一个View的时候,更新第二个View的内容,播放第二个View的时候,更新第一个View,这样可以节约特别多的内存。
这里直接放出修改后的代码全文,都是上面出现过的代码,就更改了timer内部
public class MainActivity extends AppCompatActivity
private static final long INTERVAL = 2000;
private static final long FUTURE = INTERVAL * 2;
private int listIndex = 0;
ViewAnimator viewAnimator;
String[] list = new String[]"我是第一个TextView", "我是第二个TextView", "我是第三个TextView",
"我是第四个TextView", "我是第五个TextView", "我是第六个TextView",
"我是第七个TextView", "我是第八个TextView", "我是第九个TextView",
"我是第十个TextView";
CountDownTimer timer;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewAnimator = findViewById(R.id.va);
initView();
initTimer();
private void initView()
// 只加载两个TextView轮流播放
TextView textView = new TextView(this);
textView.setText(list[0]);
TextView textView1 = new TextView(this);
viewAnimator.addView(textView);
viewAnimator.addView(textView1);
viewAnimator.setInAnimation(this, R.anim.anim_in);
viewAnimator.setOutAnimation(this, R.anim.anim_out);
private void initTimer()
timer = new CountDownTimer(FUTURE, INTERVAL)
@Override
public void onTick(long millisUntilFinished)
viewAnimator.showNext();
// 获取下个控件
int index = viewAnimator.getDisplayedChild();
TextView textView = (TextView) viewAnimator.getChildAt(
index > viewAnimator.getChildCount()? 0 : index);
// 更新下个控件的内容
textView.setText(list[listIndex++]);
// 更新数据的下标
if (listIndex >= list.length)
listIndex = 0;
@Override
public void onFinish()
timer.start();
;
timer.start();
@Override
protected void onDestroy()
super.onDestroy();
if(timer != null)
timer.cancel();
timer = null;
6. 延迟启动与内存泄漏
这是我实际开始编码之后才遇到的问题,所以另起了一篇文章,需要延迟启动功能的可以参考这篇。
https://blog.csdn.net/qq_41872247/article/details/117425890
参考材料
实现 Android TextView 文字轮播效果 - 知乎
https://zhuanlan.zhihu.com/p/62091067
8.4.2 Android动画合集之补间动画 | 菜鸟教程
https://www.runoob.com/w3cnote/android-tutorial-alphaanimation.html
以上是关于Android用ViewAnimator写一个简单的控件轮播效果的主要内容,如果未能解决你的问题,请参考以下文章