引语:20岁的金钱观,决定你30岁的生活品质!
往往在实际开发当中,需要开发者实现水平滚动或垂直滚动,水平滚动其实很简单,只需要使用跑马灯效果即可Android:不一样的TextView(一)水平滚动-跑马灯,但是如果是要实现垂直滚动该如何实现尼?
分析:对于一个垂直滚动效果,综合分析一下,无外乎以下几个问题需要处理?
1、文本使用什么控件显示?
2、如果实现上下滚动效果?
3、如何处理文本变化?
4、如何处理无限滚动的效果?
1、文本使用什么控件显示?
文本的显示当然是使用TextView进行显示,但是因为控件上的文本是不断变化的,而且是要实现上下滚动的效果,所以这里的处理是使用一组TextView显示不同文本,上下滚动的动画效果就有这一组TextView实现。
2、如果实现上下滚动效果?
上下滚动效果,使用Animation动画实现,这里要实现特定的效果,所以需要自定义Animation动画,进行translate变换,采用这个变换实现进入和退出的效果。
private class Rotate3dAnimation extends Animation {
private floatmCenterX;
private floatmCenterY;
private final booleanmTurnIn;
private final booleanmTurnUp;
private CameramCamera;//用来保存初始Camera
Rotate3dAnimation(booleanturnIn, booleanturnUp) {
mTurnIn= turnIn;
mTurnUp= turnUp;
}
@Override
public void initialize(intwidth, intheight, intparentWidth, intparentHeight) {
super.initialize(width,height,parentWidth,parentHeight);
//用来记录,初始Camera高度 宽度
mCamera=newCamera();
mCenterY= getHeight();
mCenterX= getWidth();
}
/**
* interpolatedTime 0~1
* t转换
*/
@Override
protected void applyTransformation(float interpolatedTime,Transformation t) {
final floatcenterX =mCenterX;
final floatcenterY =mCenterY;
final Camera camera =mCamera;
//标记是进入还是退出,-1进入,1推送
final intderection =mTurnUp?1: -1;
//获取转换矩阵
finalMatrix matrix = t.getMatrix();
camera.save();
if(mTurnIn) {
//进入时候,0 -> (derection * mCenterY * (interpolatedTime - 1.0f))[负值] -> 0
camera.translate(0.0f,derection *mCenterY* (interpolatedTime -1.0f),0.0f);
}else{
//退出时候,0 -> (derection * mCenterY * (interpolatedTime - 1.0f))[正值] -> 0
camera.translate(0.0f,derection *mCenterY* (interpolatedTime),0.0f);
}
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX,-centerY);
matrix.postTranslate(centerX,centerY);
}
}
3、如何处理文本变化?
在问题1中,使用一组TextView来显示文本,那么这一组TextView由谁来提供,怎么提供?
ViewSwitcher.ViewFactory视图工厂,采用视图工厂提供一组TextView,而使用TextSwitcher来实现TextView文本变化。
详解可参考:【Android开发】TextSwitcher文本转换器
这里需要复写ViewSwitcher.ViewFactory的makeView
//这里返回的TextView,就是我们看到的View,可以设置自己想要的效果
@Override
public View makeView() {
TextView textView =newTextView(mContext);
textView.setGravity(Gravity.START);
textView.setTextSize(16);
textView.setSingleLine(true);
textView.setGravity(Gravity.CENTER_VERTICAL);
textView.setEllipsize(TextUtils.TruncateAt.END);
textView.setTextColor(Color.parseColor("#555555"));
return textView;
}
4、如何处理无限轮播的效果?
这里采用Thread和Handler实现UI更新,对垂直滚动TextView的管理,我们将其封装到AutoVerticalScrollTextViewUtil类中。
Thread不断执行,通过线程池进行管理。
//定义一个执行线程
Thread thread =new Thread(new Runnable() {
@Override
public void run() {
if(mDatas==null || mDatas.size() <=0) {
//当数据源为空的时候,什么都不做
isRunning=false;
}else{
while(isRunning) {
//获取要显示的数据
currentPos=number%mDatas.size();
title=mDatas.get(currentPos);
number++;
//改变文本显示
handler.sendEmptyMessage(MESSAGE_CODE);
//停顿
Thread.sleep(duration);
}
}
}
});
//线程池进行管理
if(executorService==null || executorService.isShutdown())
executorService= Executors.newSingleThreadScheduledExecutor();
executorService.execute(thread);
通过Handler更改主线程UI
//定义Handler修改主线程
private static class MyHandler extends Handler {
//软引用
private final WeakReferencemUtil;
MyHandler(AutoVerticalScrollTextViewUtil util) {
mUtil=new WeakReference<>(util);
}
@Override
public void handleMessage(Message msg) {
AutoVerticalScrollTextViewUtil currentUtil =mUtil.get();
if(msg.what==MESSAGE_CODE) {
currentUtil.textView.next();
if(!TextUtils.isEmpty(currentUtil.title))
currentUtil.textView.setText(currentUtil.title);
}
}
}
代码处理到这里,可能又有一个疑问,如果要实现不同TextView的点击事件,该怎么办?这个其实也是很简单的,只需要把这一个TextView设置点击事件监听即可。这里的处理模式是将TextView点击处理事件交给内部接口来完成。
//控件点击事件监听
this.textView.setOnClickListener(newView.OnClickListener() {
@Override
public voidonClick(View v) {
if(onMyClickListener!=null)
onMyClickListener.onMyClickListener(currentPos,title);
}
});
//点击事件监听-内部接口,提供外部使用
public interface OnMyClickListener {
void onMyClickListener(int position,String title);
}
private OnMyClickListener onMyClickListener;
public void setOnMyClickListener(OnMyClickListener onMyClickListener) {
this.onMyClickListener= onMyClickListener;
}
处理到这里就基本上解决了所有顾虑,接下来只需要进行一下封装,之后在使用的地方进行调用,即可实现垂直滚动效果。
XML布局文件引入:
<cc.ibooker.ztextviewlib.AutoVerticalScrollTextView
android:id="@+id/autoVerticalScrollTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:paddingBottom="10dp"
android:paddingEnd="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:paddingStart="5dp"
android:paddingTop="10dp"
android:text="@string/app_name"/>
之后在Activity中进行调用:
// AutoVerticalScrollTextViewUtil.OnMyClickListener引入AutoVerticalScrollTextView点击事件监听
public class MainActivity extends AppCompatActivity implements AutoVerticalScrollTextViewUtil.OnMyClickListener {
private ArrayListlist;
private AutoVerticalScrollTextViewUtil autoVerticalScrollTextViewUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取AutoVerticalScrollTextView
AutoVerticalScrollTextView textView = (AutoVerticalScrollTextView) findViewById(R.id.autoVerticalScrollTextView);
//设置数据源
list=newArrayList<>();
for(inti =0;i <20;i++)
list.add("测试垂直滚动"+ i);
//初始化AutoVerticalScrollTextView控制器
autoVerticalScrollTextViewUtil=newAutoVerticalScrollTextViewUtil(textView,list);
//设置滚动的时间间隔
autoVerticalScrollTextViewUtil.setDuration(3000);
//开启滚动
autoVerticalScrollTextViewUtil.start();
//点击事件监听
autoVerticalScrollTextViewUtil.setOnMyClickListener(this);
}
/**
*滚动监听执行事件
*
*@paramposition滚动到list哪个position
*@paramtitleTextView文本
*/
@Override
public voidonMyClickListener(intposition,String title) {
Toast.makeText(this,list.get(position) +" --- "+ title,Toast.LENGTH_SHORT).show();
if(autoVerticalScrollTextViewUtil.getIsRunning())
//停止滚动
autoVerticalScrollTextViewUtil.stop();
else
//开启滚动
autoVerticalScrollTextViewUtil.start();
}
}
目前该功能已移步到Github:ZTextView
附述:如何使用Github ZTextView?
引入Android Studio:
在build.gradle文件中添加以下代码:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
dependencies {
compile 'com.github.zrunker:ZTextView:v1.0.1'
}
而真正的使用方式跟上述内容一样,参考:ZTextView-v1.0.0