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();
	}

	/***
	 * 重新设置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日




Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐