最后
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
欢迎大家一起交流讨论啊~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
private boolean isRunning;
/动画时间/
private int mDuration = 1000;
/动画间隔/
private int mAnimInterval = 5000;
public VerticalRollingTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.BLACK);
mPaint.setTypeface(Typeface.DEFAULT);
parseAttrs(context, attrs);
Paint.FontMetricsInt metricsInt = mPaint.getFontMetricsInt();
mTextTopToAscentOffset = metricsInt.ascent - metricsInt.top;
mAnimation.setDuration(mDuration);
}
private void parseAttrs(Context context, AttributeSet attrs) {
float density = getResources().getDisplayMetrics().density;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerticalRollingTextView);
mPaint.setColor(typedArray.getColor(R.styleable.VerticalRollingTextView_android_textColor, Color.BLACK));
mPaint.setTextSize(typedArray.getDimensionPixelOffset(R.styleable.VerticalRollingTextView_android_textSize, (int) (density * 14)));
mDuration = typedArray.getInt(R.styleable.VerticalRollingTextView_android_duration, mDuration);
mAnimInterval = typedArray.getInt(R.styleable.VerticalRollingTextView_animInterval, mAnimInterval);
typedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
// 绘制文本
if (mDataSetAdapter == null || mDataSetAdapter.isEmpty()) {
return;
}
String text1 = mDataSetAdapter.getText(mCurrentIndex);
String text2 = mDataSetAdapter.getText(mNextIndex);
//只需要进行一次测量
if (mOrgOffsetY == -1) {
mPaint.getTextBounds(text1, 0, text1.length(), bounds);
mOffset = (getHeight() + bounds.height()) * 0.5f;
mOrgOffsetY = mCurrentOffsetY = mOffset - mTextTopToAscentOffset;
mAnimation.updateValue(mOrgOffsetY, -2 * mTextTopToAscentOffset);
}
canvas.drawText(text1, 0, mCurrentOffsetY, mPaint);
canvas.drawText(text2, 0, mCurrentOffsetY + mOffset + mTextTopToAscentOffset, mPaint);
}
public void setDataSetAdapter(DataSetAdapter dataSetAdapter) {
mDataSetAdapter = dataSetAdapter;
confirmNextIndex();
invalidate();
}
/**
- 开始转动,界面可见的时候调用
*/
public void run() {
if (isRunning) {
return;
}
isRunning = true;
mAnimation.updateValue(mCurrentOffsetY, -2 * mTextTopToAscentOffset);
post(mRollingTask);
}
/**
- @return true代表正在转动
*/
public boolean isRunning() {
return isRunning;
}
/**
- 停止转动,界面不可见的时候调用
*/
public void stop() {
isRunning = false;
removeCallbacks(mRollingTask);
}
Runnable mRollingTask = new Runnable() {
@Override
public void run() {
mAnimationEnded = false;
startAnimation(mAnimation);
postDelayed(this, mAnimInterval);
}
};
public void animationEnd() {
//1.角标+1
mCurrentIndex++;
//2.计算出正确的角标
mCurrentIndex = mCurrentIndex < mDataSetAdapter.getItemCount() ? mCurrentIndex : mCurrentIndex % mDataSetAdapter.getItemCount();
//3.计算下一个待显示文字角标
confirmNextIndex();
//3.位置复位
mCurrentOffsetY = mOrgOffsetY;
mAnimationEnded = true;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mRollingTask);
if (isRunning()) {
mAnimation.cancel();
}
}
/**
- 计算第二个角标
*/
private void confirmNextIndex() {
//3.计算第二个角标
mNextIndex = mCurrentIndex + 1;
//4.计算出正确的第二个角标
mNextIndex = mNextIndex < mDataSetAdapter.getItemCount() ? mNextIndex : 0;
}
/**
-
float估值器
-
@param fraction
-
@param startValue
-
@param endValue
-
@return
*/
float evaluate(float fraction, float startValue, float endValue) {
return startValue + fraction * (endValue - startValue);
}
@Override
public void setOnClickListener(OnClickListener l) {
}
public void setOnItemClickListener(final OnItemClickListener onItemClickListener) {
super.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onItemClickListener.onItemClick(VerticalRollingTextView.this, mCurrentIndex);
}
});
}
public interface OnItemClickListener {
void onItemClick(VerticalRollingTextView view, int index);
}
class InternalAnimation extends Animation {
float startValue;
float endValue;
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (mAnimationEnded) return;
mCurrentOffsetY = evaluate(interpolatedTime, startValue, endValue);
if (mCurrentOffsetY == endValue) {
try {
animationEnd();
}catch (Exception e) {
e.printStackTrace();
}
新的开始
改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。
《系列学习视频》
《系列学习文档》
《我的大厂面试之旅》
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
-yxPRDpq2-1714814309480)]
《系列学习文档》
[外链图片转存中…(img-JTvFWO5j-1714814309481)]
《我的大厂面试之旅》
[外链图片转存中…(img-qjyHv7qf-1714814309481)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!