您的位置:首页 > 移动开发 > Android开发

Android:TextView的垂直滚动效果和上下滚动效果,原生动画实现

2017-01-19 16:04 1031 查看

1 效果图

啥也不多说,看效果图,



2 实现原理

A利用平移动画TranslateAnimation完成动画向上向下平移

B得到控件的LayoutParams设置控件的宽高、Margins(设置TextView的宽高为最外部容器的宽高)

3 附源码

代码中提供方法setCurText 设置当前的文字,无动画,upText显示上升动画,downText显示下降动画,更多的功能(设置字体大小、字体样式)请自行添加

package com.odds.odds.start;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;

public class UpDownTextView extends LinearLayout {
private Context mContext;
private TextView textViewTop, textViewCenter, textViewBottom;

private LinearLayout llayout;

private String curText = null;

private int mHeight = 0;

public UpDownTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initViews();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight = h;
textViewTop = addText();
textViewCenter = addText();
textViewBottom = addText();
resizeLL();
}

private void initViews() {

llayout = new LinearLayout(mContext);
llayout.setOrientation(LinearLayout.VERTICAL);
this.addView(llayout);
}

private void resizeLL() {
LayoutParams lp2 = (LayoutParams) llayout.getLayoutParams();
lp2.height = mHeight * (llayout.getChildCount());
lp2.setMargins(0, -mHeight, 0, 0);// 使向上偏移一定的高度,用padding,scrollTo都分有问题
llayout.setLayoutParams(lp2);
}

private TextView addText() {
TextView tv = new TextView(mContext);
tv.setGravity(Gravity.CENTER);
tv.setTextSize(22);
llayout.addView(tv);
LayoutParams lp = (LayoutParams) tv.getLayoutParams();
lp.height = mHeight;
lp.width = getWidth();
tv.setLayoutParams(lp);
return tv;
}

/***
* 设置初始的字
*
* @param curText
*/
public void setCurText(String curText) {
this.curText = curText;
textViewCenter.setText(curText);
}

/***
* 向上弹动画
*
* @param curText
*/
public void upText(String curText) {
this.curText = curText;
textViewBottom.setText(curText);
up();// 向上的动画
}

public void downText(String curText) {
this.curText = curText;
textViewTop.setText(curText);
down();// 向上的动画
}

/***
* 向上动画
*/
private void up() {
llayout.clearAnimation();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, -mHeight);
animation.setDuration(1500);
llayout.startAnimation(animation);
animation.setAnimationListener(listener);
}

/***
* 向下动画
*/
public void down() {
llayout.clearAnimation();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, mHeight);
animation.setDuration(1500);
llayout.startAnimation(animation);
animation.setAnimationListener(listener);
}

/***
* 动画监听,动画完成后,动画恢复,设置文本
*/
private AnimationListener listener = new AnimationListener() {

@Override
public void onAnimationStart(Animation arg0) {
}

@Override
public void onAnimationRepeat(Animation arg0) {
}

@Override
public void onAnimationEnd(Animation arg0) {
setCurText(curText);
}
};

}

2016年1月19日



4 改进版

package com.odds.odds.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;

public class UpDownTextView extends LinearLayout {
private Context mContext;
private TextView textViews[] = new TextView[3];

private LinearLayout llayout;

private String curText = null;

private int mHeight = 0;
private int mDuring=500;

public UpDownTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initViews();
}

private void initViews() {
llayout = new LinearLayout(mContext);
llayout.setOrientation(LinearLayout.VERTICAL);
this.addView(llayout);

textViews[0] = addText();
textViews[1] = addText();
textViews[2] = addText();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight = h;
setViewsHeight();//
}

private void setViewsHeight() {
for (TextView tv : textViews) {
LayoutParams lp = (LayoutParams) tv.getLayoutParams();
lp.height = mHeight;
lp.width = getWidth();
tv.setLayoutParams(lp);
}

LayoutParams lp2 = (LayoutParams) llayout.getLayoutParams();
lp2.height = mHeight * (llayout.getChildCount());
lp2.setMargins(0, -mHeight, 0, 0);// 使向上偏移一定的高度,用padding,scrollTo都分有问题
llayout.setLayoutParams(lp2);
}

public void setGravity(int graty) {
for (TextView tv : textViews) {
tv.setGravity(graty);
}
}

public void setTextSize(int dpSize) {
for (TextView tv : textViews) {
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dpSize);
}
}

public void setTextColor(int color) {
for (TextView tv : textViews) {
tv.setTextColor(color);
}
}

private TextView addText() {
TextView tv = new TextView(mContext);
tv.setGravity(Gravity.CENTER_VERTICAL);
llayout.addView(tv);
return tv;
}

/***
* 设置初始的字
*
* @param curText
*/
public void setText(String curText) {
this.curText = curText;
textViews[1].setText(curText);
}

/***
* 向上弹动画
*
* @param curText
*/
public void setTextUpAnim(String text) {
this.curText = text;
textViews[2].setText(text);
up();// 向上的动画
}

public void setTextDownAnim(String text) {
this.curText = text;
textViews[0].setText(text);
down();// 向上的动画
}

public void setDuring(int during){
this.mDuring=during;
}
/***
* 向上动画
*/
private void up() {
llayout.clearAnimation();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, -mHeight);
animation.setDuration(mDuring);
llayout.startAnimation(animation);
animation.setAnimationListener(listener);
}

/***
* 向下动画
*/
public void down() {
llayout.clearAnimation();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, mHeight);
animation.setDuration(mDuring);
llayout.startAnimation(animation);
animation.setAnimationListener(listener);
}

/***
* 动画监听,动画完成后,动画恢复,设置文本
*/
private AnimationListener listener = new AnimationListener() {

@Override
public void onAnimationStart(Animation arg0) {
}

@Override
public void onAnimationRepeat(Animation arg0) {
}

@Override
public void onAnimationEnd(Animation arg0) {
setText(curText);
}
};

}

2016年1月20日

5 改进第二版

package com.example.testt;

import java.util.List;

import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;

public class UpDownTextView extends LinearLayout {
private Context mContext;
private TextView textViews[] = new TextView[3];

private LinearLayout llayout;

private String curText = null;

/***
* 动画时间
*/
private int mAnimTime = 500;

/**
* 停留时间
*/
private int mStillTime = 500;

/***
* 轮播的string
*/
private List<String> mTextList;

/***
* 当前轮播的索引
*/
private int currentIndex = 0;

/***
* 动画模式
*/
private int animMode = 0;// 默认向上 0--向上,1--向下

public final static int ANIM_MODE_UP = 0;
public final static int ANIM_MODE_DOWN = 1;

private TranslateAnimation animationDown, animationUp;

public UpDownTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initViews();
}

private void initViews() {
llayout = new LinearLayout(mContext);
llayout.setOrientation(LinearLayout.VERTICAL);
this.addView(llayout);

textViews[0] = addText();
textViews[1] = addText();
textViews[2] = addText();
}

/***
* 当界面销毁时
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopAutoScroll();// 防止内存泄漏的操作
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setViewsHeight();
}

/***

d89f
* 重新设置VIEW的高度
*/
private void setViewsHeight() {
for (TextView tv : textViews) {
LayoutParams lp = (LayoutParams) tv.getLayoutParams();
lp.height = getHeight();
lp.width = getWidth();
tv.setLayoutParams(lp);
}

LayoutParams lp2 = (LayoutParams) llayout.getLayoutParams();
lp2.height = getHeight() * (llayout.getChildCount());
lp2.setMargins(0, -getHeight(), 0, 0);// 使向上偏移一定的高度,用padding,scrollTo都分有问题
llayout.setLayoutParams(lp2);
}

// /////////////////////以下是一些基本的方法textView要用到///////////////////////////////////

public void setGravity(int graty) {
for (TextView tv : textViews) {
tv.setGravity(graty);
}
}

public void setTextSize(int dpSize) {
for (TextView tv : textViews) {
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dpSize);
}
}

public void setTextColor(int color) {
for (TextView tv : textViews) {
tv.setTextColor(color);
}
}

private TextView addText() {
TextView tv = new TextView(mContext);
tv.setGravity(Gravity.CENTER_VERTICAL);
llayout.addView(tv);
return tv;
}

/***
* 设置初始的字
*
* @param curText
*/
public void setText(String curText) {
this.curText = curText;
textViews[1].setText(curText);
}

/***
* 开始自动滚动
*/
public void startAutoScroll() {
if (mTextList == null || mTextList.size() == 0) {
return;
}
// 先停止
stopAutoScroll();
this.postDelayed(runnable, mStillTime);// 可用runnable来代替hander或者 timer
}

/***
* 停止自动滚动
*/
public void stopAutoScroll() {
this.removeCallbacks(runnable);
}

private Runnable runnable = new Runnable() {
@Override
public void run() {
currentIndex = (currentIndex) % mTextList.size();
switch (animMode) {
case ANIM_MODE_UP:
setTextUpAnim(mTextList.get(currentIndex));
break;
case ANIM_MODE_DOWN:
setTextDownAnim(mTextList.get(currentIndex));
break;
}
currentIndex++;
UpDownTextView.this.postDelayed(runnable, mStillTime + mAnimTime);

}
};

/***
* 向上弹动画
*
* @param curText
*/
public void setTextUpAnim(String text) {
this.curText = text;
textViews[2].setText(text);
up();// 向上的动画
}

public void setTextDownAnim(String text) {
this.curText = text;
textViews[0].setText(text);
down();// 向上的动画
}

public void setDuring(int during) {
this.mAnimTime = during;
}

/***
* 向上动画
*/
private void up() {
llayout.clearAnimation();
if (animationUp == null)
animationUp = new TranslateAnimation(0, 0, 0, -getHeight());
animationUp.setDuration(mAnimTime);
llayout.startAnimation(animationUp);
animationUp.setAnimationListener(listener);
}

/***
* 向下动画
*/
public void down() {
llayout.clearAnimation();
if (animationDown == null)
animationDown = new TranslateAnimation(0, 0, 0, getHeight());
animationDown.setDuration(mAnimTime);
llayout.startAnimation(animationDown);
animationDown.setAnimationListener(listener);
}

/***
* 动画监听,动画完成后,动画恢复,设置文本
*/
private AnimationListener listener = new AnimationListener() {

@Override
public void onAnimationStart(Animation arg0) {
}

@Override
public void onAnimationRepeat(Animation arg0) {
}

@Override
public void onAnimationEnd(Animation arg0) {
setText(curText);
}
};

public int getAnimTime() {
return mAnimTime;
}

public void setAnimTime(int mAnimTime) {
this.mAnimTime = mAnimTime;
}

public int getStillTime() {
return mStillTime;
}

public void setStillTime(int mStillTime) {
this.mStillTime = mStillTime;
}

public List<String> getTextList() {
return mTextList;
}

public void setTextList(List<String> mTextList) {
this.mTextList = mTextList;
}

public int getCurrentIndex() {
return currentIndex;
}

public void setCurrentIndex(int currentIndex) {
this.currentIndex = currentIndex;
}

public int getAnimMode() {
return animMode;
}

public void setAnimMode(int animMode) {
this.animMode = animMode;
}

}


6 修正bug版

经测试在7.0系统下无法正常显示,所以作了一点点修正
当onsizeChanged 时,需要延时处理才能设置高度,加上post后面做要做的事即可

package com.caiyu.qqsd.lib.widget;

import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.caiyu.qqsd.common.interfaceImpl.AnimationListenerImpl;

import java.util.List;

/**
* 上下滚动的TEXTVIEW
* Created by liugd on 2017/3/20.
*/
public class UpDownTextView extends LinearLayout {
private Context mContext;
private TextView textViews[] = new TextView[3];

private LinearLayout llayout;

private String curText = null;

/***
* 动画时间
*/
private int mAnimTime = 500;

/**
* 停留时间
*/
private int mStillTime = 3500;

/***
* 轮播的string
*/
private List<String> mTextList;

/***
* 当前轮播的索引
*/
private int currentIndex = 0;

/***
* 动画模式
*/
private int animMode = 0;// 默认向上 0--向上,1--向下

/***
* 是否正在自动滚动
*/
private boolean isRunning = false;

public final static int ANIM_MODE_UP = 0;
public final static int ANIM_MODE_DOWN = 1;

private TranslateAnimation animationDown, animationUp;

public UpDownTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
if (!isInEditMode())
initViews();
}

private void initViews() {
llayout = new LinearLayout(mContext);
llayout.setOrientation(LinearLayout.VERTICAL);
this.addView(llayout);

textViews[0] = addText();
textViews[1] = addText();
textViews[2] = addText();
}

/***
* 当界面销毁时
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopAutoScroll();// 防止内存泄漏的操作
//        LogUitls.print("滚动文本","界面销毁移动handler");
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (!isInEditMode()) {
post(new Runnable() {//7.0以后,需要界面可见时,设置宽高才有效果
@Override
public void run() {
setViewsHeight();
}
});
}
}

/***
* 重新设置VIEW的高度
*/
private void setViewsHeight() {
for (TextView tv : textViews) {
LayoutParams lp = (LayoutParams) tv.getLayoutParams();
lp.height = getHeight();
lp.width = getWidth();
tv.setLayoutParams(lp);
}

LayoutParams lp2 = (LayoutParams) llayout.getLayoutParams();
lp2.height = getHeight() * (llayout.getChildCount());
lp2.setMargins(0, -getHeight(), 0, 0);// 使向上偏移一定的高度,用padding,scrollTo都分有问题
llayout.setLayoutParams(lp2);
}

// /////////////////////以下是一些基本的方法textView要用到///////////////////////////////////

public void setGravity(int graty) {
for (TextView tv : textViews) {
tv.setGravity(graty);
}
}

public void setTextSize(int dpSize) {
for (TextView tv : textViews) {
tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, dpSize);
}
}

public void setTextColor(int color) {
for (TextView tv : textViews) {
tv.setTextColor(color);
}
}

private TextView addText() {
TextView tv = new TextView(mContext);
tv.setGravity(Gravity.CENTER_VERTICAL);
llayout.addView(tv);
return tv;
}

/***
* 设置初始的字
*
* @param curText
*/
public void setText(String curText) {
this.curText = curText;
textViews[1].setText(curText);
}

/***
* 开始自动滚动
*/
public void startAutoScroll() {
if (!isRunning) {
isRunning = true;
if (mTextList == null || mTextList.size() == 0) {
stopAutoScroll();
return;
}
this.postDelayed(runnable, mStillTime + mAnimTime);// 可用runnable来代替hander或者 timer
}
}

/***
* 停止自动滚动
*/
public void stopAutoScroll() {
if (isRunning) {
isRunning = false;
this.removeCallbacks(runnable);
}
}

private Runnable runnable = new Runnable() {
@Override
public void run() {
currentIndex++;
currentIndex = (currentIndex) % mTextList.size();
switch (animMode) {
case ANIM_MODE_UP:
setTextUpAnim(mTextList.get(currentIndex));
break;
case ANIM_MODE_DOWN:
setTextDownAnim(mTextList.get(currentIndex));
break;
}
UpDownTextView.this.postDelayed(runnable, mStillTime + mAnimTime);
if (onTextScrollListener != null) {
onTextScrollListener.onTextScroll();
}
//            LogUitls.print("滚动文本", "界面滚动");
}
};

/***
* 向上弹动画
*
* @param curText
*/
public void setTextUpAnim(String curText) {
this.curText = curText;
textViews[2].setText(curText);
up();// 向上的动画
}

public void setTextDownAnim(String text) {
this.curText = text;
textViews[0].setText(text);
down();// 向上的动画
}

public void setDuring(int during) {
this.mAnimTime = during;
}

/***
* 向上动画
*/
private void up() {
llayout.clearAnimation();
if (animationUp == null)
animationUp = new TranslateAnimation(0, 0, 0, -getHeight());
animationUp.setDuration(mAnimTime);
llayout.startAnimation(animationUp);
animationUp.setAnimationListener(listener);
}

/***
* 向下动画
*/
public void down() {
llayout.clearAnimation();
if (animationDown == null)
animationDown = new TranslateAnimation(0, 0, 0, getHeight());
animationDown.setDuration(mAnimTime);
llayout.startAnimation(animationDown);
animationDown.setAnimationListener(listener);
}

/***
* 动画监听,动画完成后,动画恢复,设置文本
*/
private AnimationListener listener = new AnimationListenerImpl() {
@Override
public void onAnimationEnd(Animation arg0) {
setText(curText);
}
};

public int getAnimTime() {
return mAnimTime;
}

public void setAnimTime(int mAnimTime) {
this.mAnimTime = mAnimTime;
}

public int getStillTime() {
return mStillTime;
}

public void setStillTime(int mStillTime) {
this.mStillTime = mStillTime;
}

public List<String> getTextList() {
return mTextList;
}

public void setTextList(List<String> mTextList) {
this.mTextList = mTextList;
}

public int getCurrentIndex() {
return currentIndex;
}

public void setCurrentIndex(int currentIndex) {
this.currentIndex = currentIndex;
}

public int getAnimMode() {
return animMode;
}

public void setAnimMode(int animMode) {
this.animMode = animMode;
}

public void setSingleLine() {
for (TextView tv : textViews) {
tv.setSingleLine();
tv.setEllipsize(TextUtils.TruncateAt.END);//尾部打省略号
}
}

OnTextScrollListener onTextScrollListener;

public void setOnTextScrollListener(OnTextScrollListener onTextScrollListener) {
this.onTextScrollListener = onTextScrollListener;
}

public interface OnTextScrollListener {
void onTextScroll();
}

}


调用方法

public void fun(){
final UpDownTextView textView = (UpDownTextView) findViewById(R.id.textView1);
final ArrayList<String> titleList = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
titleList.add(i + "");
}
textView.setTextList(titleList);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
textView.startAutoScroll();
}
});
}


布局十分简单,我就不贴出来了

http://download.csdn.net/detail/u012990509/9786599  (左边下载地址),下载地址中的代码不是最新的,因CSDN限制不能更新,所以请以最后更新的为准

 
2017年8月31日
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息