写在开头
textview,在android中算是很平常的一个控件了,但是基于它的使用还是可以有很多的扩展的!在这总结了下以前项目中用的一些使用,记录下来,供自己还有他人学习!在这分为四部分:
1. textview跑马灯效果,及多条textiview同时滚动出现的问题及解决!
2. 仿淘宝竖直滚动的textview
3. 仿支付宝自动滚动到某一个数字的自定义效果
4. 富文本实现各种组合自定义textview
demo地址:https://github.com/loveAndroidAndroid/android-study
效果图如下
多条跑马灯效果(具体demo看文末链接)
一个textview的跑马灯效果通过修改layout文件就可以,如下:
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
//循环滚动
android:marqueeRepeatLimit="marquee_forever"
当要求多条textview同时滚动时会出现一些问题,会发现只有一条在滚动,其实这是焦点的问题,因为只有一个textview右焦点。其实解决也不麻烦,我们要自定义我们的自己的textview
public class FocusedTextView extends TextView {
public FocusedTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public FocusedTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FocusedTextView(Context context) {
super(context);
}
// 检测有没有焦点 返回true 让TextView认为有焦点
@Override
public boolean isFocused() {
return true;
}
// 焦点的改变
@Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
// 注意参1 改成true 就算焦点改变 也不会停止跑马灯,因为在此处返回true,text默认都有焦点
super.onFocusChanged(true, direction, previouslyFocusedRect);
}
}
仿淘宝竖直滚动textview
这里也是通过自定义textview实现。
public class ScrollTextView extends TextSwitcher implements ViewSwitcher.ViewFactory {
private Context context;
// inAnimation,outAnimation分别构成翻页的进出动画
private ScrollAnimation inAnimation;
private ScrollAnimation outAnimation;
private String titleLeft;
public ScrollTextView(Context context) {
this(context, null);
}
public ScrollTextView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
//创建两个view
setFactory(this);
inAnimation = createAnim(-90, 0, true, true);
outAnimation = createAnim(0, 90, false, true);
//设置动画
setInAnimation(inAnimation);
setOutAnimation(outAnimation);
}
private ScrollAnimation createAnim(float start, float end, boolean turnIn,
boolean turnUp) {
final ScrollAnimation rotation = new ScrollAnimation(start, end,
turnIn, turnUp);
//设置时间
rotation.setDuration(800);
rotation.setFillAfter(false);
rotation.setInterpolator(new AccelerateInterpolator());
return rotation;
}
/**
* 这里返回的TextView,就是我们看到的View
*/
@Override
public View makeView() {
TextView textView = new TextView(context);
textView.setGravity(Gravity.LEFT);
textView.setTextSize(15);
textView.setTextColor(Color.WHITE);
textView.setGravity(Gravity.CENTER_VERTICAL);// gravity center_vertical
textView.setText("");
textView.setSingleLine(true);
textView.setEllipsize(TextUtils.TruncateAt.END);
return textView;
}
public void next() {
if (getInAnimation() != inAnimation) {
setInAnimation(inAnimation);
}
if (getOutAnimation() != outAnimation) {
setOutAnimation(outAnimation);
}
}
//滚动动画
class ScrollAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private float mCenterX;
private float mCenterY;
private final boolean mTurnIn;
private final boolean mTurnUp;
private Camera mCamera;
public ScrollAnimation(float fromDegrees, float toDegrees,
boolean turnIn, boolean turnUp) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mTurnIn = turnIn;
mTurnUp = turnUp;
}
@Override
public void initialize(int width, int height, int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
mCenterY = getHeight() / 2;
mCenterX = getWidth() / 2;
}
@Override
protected void applyTransformation(float interpolatedTime,
Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees
+ ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final int derection = mTurnUp ? 1 : -1;
final Matrix matrix = t.getMatrix();
camera.save();
if (mTurnIn) {
camera.translate(0.0f, derection * mCenterY
* (interpolatedTime - 1.0f), 0.0f);
} else {
camera.translate(0.0f, derection * mCenterY
* (interpolatedTime), 0.0f);
}
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
}
自动滚动textview
滚动动画只用值动画ValueAnimator 实现。可设置内容类型,动画时间等!
本实现参考大神博客,又不懂的大家讨论。
/**
* 数字滚动的textView
*/
public class NumberRunningTextView extends TextView {
private static final int MONEY_TYPE = 0;
private static final int NUM_TYPE = 1;
private int textType;//内容的类型,默认是金钱类型
private boolean useCommaFormat;//是否使用每三位数字一个逗号的格式,让数字显得比较好看,默认使用
private boolean runWhenChange;//是否当内容有改变才使用动画,默认是
private int duration;//动画的周期,默认为1000ms
private int minNum;//显示数字最少要达到这个数字才滚动 默认为1
private float minMoney;//显示金额最少要达到这个数字才滚动 默认为0.3
private DecimalFormat formatter = new DecimalFormat("0.00");// 格式化金额,保留两位小数
private String preStr;
public NumberRunningTextView(Context context) {
this(context, null);
}
public NumberRunningTextView(Context context, AttributeSet attrs) {
this(context, attrs, android.R.attr.textViewStyle);
}
public NumberRunningTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NumberRunningTextView);
duration = ta.getInt(R.styleable.NumberRunningTextView_duration, 1000);
textType = ta.getInt(R.styleable.NumberRunningTextView_textType, MONEY_TYPE);
useCommaFormat = ta.getBoolean(R.styleable.NumberRunningTextView_useCommaFormat, true);
runWhenChange = ta.getBoolean(R.styleable.NumberRunningTextView_runWhenChange,true);
minNum = ta.getInt(R.styleable.NumberRunningTextView_minNum, 3);
minMoney = ta.getFloat(R.styleable.NumberRunningTextView_minMoney,0.1f);
ta.recycle();
}
/**
* 设置需要滚动的金钱(必须为正数)或整数(必须为正数)的字符串
*
* @param str
*/
public void setContent(String str) {
//如果是当内容改变的时候才执行滚动动画,判断内容是否有变化
if (runWhenChange){
if (TextUtils.isEmpty(preStr)){
//如果上一次的str为空
preStr = str;
useAnimByType(str);
return;
}
//如果上一次的str不为空,判断两次内容是否一致
if (preStr.equals(str)){
//如果两次内容一致,则不做处理
return;
}
preStr = str;//如果两次内容不一致,记录最新的str
}
useAnimByType(str);
}
private void useAnimByType(String str) {
if (textType == MONEY_TYPE) {
playMoneyAnim(str);
} else if (textType == NUM_TYPE){
playNumAnim(str);
}
}
/**
* 播放金钱数字动画的方法
*
* @param moneyStr
*/
public void playMoneyAnim(String moneyStr) {
String money = moneyStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号
try {
float finalFloat = Float.parseFloat(money);
if (finalFloat < minMoney) {
//如果传入的为0,则直接使用setText()
setText(moneyStr);
return;
}
ValueAnimator floatAnimator = ValueAnimator.ofFloat(0, finalFloat);
floatAnimator.setDuration(duration);
floatAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentNum = (float) animation.getAnimatedValue();
String str = formatter.format(Double.parseDouble(String.valueOf(currentNum)));//格式化成两位小数
// 更新显示的内容
if (useCommaFormat) {
//使用每三位数字一个逗号的格式
String formatStr = StringUtils.addComma(str);//三位一个逗号格式的字符串
setText(formatStr);
} else {
setText(str);
}
}
});
floatAnimator.start();
} catch (NumberFormatException e) {
e.printStackTrace();
this.setText(moneyStr);//如果转换Double失败则直接用setText
}
}
/**
* 播放数字动画的方法
*
* @param numStr
*/
public void playNumAnim(String numStr) {
String num = numStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号
try {
int finalNum = Integer.parseInt(num);
if (finalNum < minNum) {
//由于是整数,每次是递增1,所以如果传入的数字比帧数小,则直接使用setText()
this.setText(numStr);
return;
}
ValueAnimator intAnimator = new ValueAnimator().ofInt(0, finalNum);
intAnimator.setDuration(duration);
intAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int currentNum = (int) animation.getAnimatedValue();
setText(String.valueOf(currentNum));
}
});
intAnimator.start();
} catch (NumberFormatException e) {
e.printStackTrace();
setText(numStr);//如果转换Double失败则直接用setText
}
}
}
使用很简单了
tvMoney.setContent("1454.00");
tvNum.setContent("300");
富文本实现各种效果
以前总结过,想看的请看下面链接,其中还要一些别的总结!
http://blog.youkuaiyun.com/say_from_wen/article/details/76177299
写在文末
关于textview的使用,大家有什么好的自定义和别人大神的链接也发出来,一起学习,共同进步!