Android——仿京东垂直滚动广告栏

效果图:

实现仿京东垂直滚动广告栏,它是一个动态的无限自动轮播图,让我们看看它是怎么实现的:

先看一看布局文件:

activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.bawei.com.wangruixin20171116.MainActivity">

    <com.bawei.com.wangruixin20171116.ADTextView
        android:id="@+id/re"
        android:layout_width="match_parent"
        android:layout_height="20dp" />
</RelativeLayout>

MainActivitypublic class MainActivity extends AppCompatActivity {

private ADTextView mADTextView1;
private ArrayList<ADEnity> mList;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();


}
public void init(){
mADTextView1 = (ADTextView) findViewById(R.id.re);
mList = new ArrayList<>();
mList.add(new ADEnity("推荐","国货PK美国货,结果让人震惊", "连接1"));
mList.add(new ADEnity("推荐","这次XiPhone,可能让你迷路", "连接2"));
mList.add(new ADEnity("HOT", "为什么吉普,奥巴马都爱钓鱼", "连接3"));
mList.add(new ADEnity("HOT", "虽然我字难看,但我钢笔好看啊", "连接4"));
mADTextView1.setSpeed(3);
mADTextView1.setInterval(1500);
mADTextView1.setFrontColor(Color.RED);
mADTextView1.setBackColor(Color.BLACK);
mADTextView1.setmTexts(mList);
// mADTextView.setOnItemClickListener(new ADTextView.OnItemClickListener() {
// @Override
// public void onClick(String mUrl) {
// if (mToast == null) {
// mToast = Toast.makeText(getActivity(), mUrl, Toast.LENGTH_LONG);
// } else {
// mToast.setText(mUrl);
// }
// mToast.show();
// }
// });

}
}

ADEnitypublic class ADEnity {
private String mFront ; //前面的文字
private String mBack ; //后面的文字
private String mUrl ;//包含的链接

public ADEnity(String mFront, String mBack,String mUrl) {
this.mFront = mFront;
this.mBack = mBack;
this.mUrl = mUrl;
}

public String getmUrl() {
return mUrl;
}

public void setmUrl(String mUrl) {
this.mUrl = mUrl;
}

public String getmFront() {
return mFront;
}

public void setmFront(String mFront) {
this.mFront = mFront;
}

public String getmBack() {
return mBack;
}

public void setmBack(String mBack) {
this.mBack = mBack;
}
}

ADTextView/**
* 仿京东垂直滚动广告栏
*
*/

public class ADTextView extends View {
private int mSpeed; //文字出现或消失的速度 建议1~5
private int mInterval; //文字停留在中间的时长
private int mFrontColor; //前缀颜色
private int mContentColor; //内容的颜色
private int mFrontTextSize; //前缀文字大小
private int mContentTextSize; //内容文字大小

private List<ADEnity> mTexts; //显示文字的数据源
private int mY = 0; //文字的Y坐标
private int mIndex = 0; //当前的数据下标
private Paint mPaintContent; //绘制内容的画笔
private Paint mPaintFront; //绘制前缀的画笔
private boolean isMove = true; //文字是否移动
private String TAG = "ADTextView";
private boolean hasInit = false;
private boolean isPaused = false;

public interface onClickListener {
public void onClick(String mUrl);
}

private onClickListener onClickListener;

public void setOnClickListener(onClickListener onClickListener) {
this.onClickListener = onClickListener;
}

public ADTextView(Context context) {
this(context, null);
}

public ADTextView(Context context, AttributeSet attrs) {
super(context, attrs);
obtainStyledAttrs(attrs);
init();
}

//获取资源文件
private void obtainStyledAttrs(AttributeSet attrs) {
TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.ADTextView);
mSpeed = array.getInt(R.styleable.ADTextView_ad_text_view_speed, 1);
mInterval = array.getInt(R.styleable.ADTextView_ad_text_view_interval, 2000);
mFrontColor = array.getColor(R.styleable.ADTextView_ad_text_front_color, Color.RED);
mContentColor = array.getColor(R.styleable.ADTextView_ad_text_content_color, Color.BLACK);
mFrontTextSize = (int) array.getDimension(R.styleable.ADTextView_ad_text_front_size, SizeUtil.Sp2Px(getContext(), 15));
mContentTextSize = (int) array.getDimension(R.styleable.ADTextView_ad_text_content_size, SizeUtil.Sp2Px(getContext(), 15));
array.recycle();
}

@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();

switch (action) {
case MotionEvent.ACTION_DOWN:
if (onClickListener != null) {
onClickListener.onClick(mTexts.get(mIndex).getmUrl());
}

break;
}
return true;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(DensityUtil.dip2px(getContext(), 500), DensityUtil.dip2px(getContext(), 40));
}

//测量宽度
private int measureHeight(int heightMeasureSpec) {
int result = 0;
int mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);

if (mode == MeasureSpec.EXACTLY) {
result = size;
} else { //高度至少为两倍字高
int mfronTextHeight = (int) (mPaintFront.descent() - mPaintFront.ascent()); //前缀文字字高
int mContentTextHeight = (int) (mPaintContent.descent() - mPaintContent.ascent()); //内容文字字高
result = Math.max(mfronTextHeight, mContentTextHeight) * 2;

if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}

//测量高度
private int measureWidth(int widthMeasureSpec) {
int result = 0;
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else { //宽度最小十个字的宽度
String text = "十个字十个字十个字字";
Rect rect = new Rect();
mPaintContent.getTextBounds(text, 0, text.length(), rect);
result = rect.right - rect.left;
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}

//设置数据源
public void setmTexts(List<ADEnity> mTexts) {
this.mTexts = mTexts;
}

//设置广告文字的停顿时间
public void setInterval(int mInterval) {
this.mInterval = mInterval;
}

//设置速度
public void setSpeed(int spedd) {
this.mSpeed = spedd;
}

//设置前缀的文字颜色
public void setFrontColor(int mFrontColor) {
mPaintFront.setColor(mFrontColor);
}

//设置正文内容的颜色
public void setBackColor(int mBackColor) {
mPaintContent.setColor(mBackColor);
}

//初始化默认值
private void init() {
mIndex = 0;
mPaintFront = new Paint();
mPaintFront.setAntiAlias(true);
mPaintFront.setDither(true);
mPaintFront.setTextSize(mFrontTextSize);
mPaintFront.setColor(mFrontColor);

mPaintContent = new Paint();
mPaintContent.setAntiAlias(true);
mPaintContent.setDither(true);
mPaintContent.setTextSize(mContentTextSize);
mPaintContent.setColor(mContentColor);

}

@Override
protected void onDraw(Canvas canvas) {
if (mTexts != null) {
ADEnity model = mTexts.get(mIndex);
String font = model.getmFront();
String back = model.getmBack();
//绘制前缀
Rect indexBound = new Rect();
mPaintFront.getTextBounds(font, 0, font.length(), indexBound);

//绘制内容文字
Rect contentBound = new Rect();
mPaintContent.getTextBounds(back, 0, back.length(), contentBound);
if (mY == 0 && hasInit == false) {
mY = getMeasuredHeight() - indexBound.top;
hasInit = true;
}
//移动到最上面
if (mY <= 0 - indexBound.bottom) {
Log.i(TAG, "onDraw: " + getMeasuredHeight());
mY = getMeasuredHeight() - indexBound.top;
mIndex++;
isPaused = false;
}
canvas.drawText(back, 0, back.length(), (indexBound.right - indexBound.left) + 20, mY, mPaintContent);
canvas.drawText(font, 0, font.length(), 10, mY, mPaintFront);
//移动到中间
if (!isPaused && mY <= getMeasuredHeight() / 2 - (indexBound.top + indexBound.bottom) / 2) {
isMove = false;
isPaused = true;
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
postInvalidate();
isMove = true;
}
}, mInterval);
}
mY -= mSpeed;
//循环使用数据
if (mIndex == mTexts.size()) {
mIndex = 0;
}
//如果是处于移动状态时的,则延迟绘制
//计算公式为一个比例,一个时间间隔移动组件高度,则多少毫秒来移动1像素
if (isMove) {
postInvalidateDelayed(2);
}
}

}
}

DensityUtilpublic class DensityUtil {
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}

/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
}

SizeUtilpublic class SizeUtil {
public static int Dp2Px(Context context, int dpi) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpi, context.getResources().getDisplayMetrics());
}
public static int Px2Dp(Context context, int px) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, context.getResources().getDisplayMetrics());
}
public static int Sp2Px(Context context, int sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
}
public static int Px2Sp(Context context, int px) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, context.getResources().getDisplayMetrics());
}
}

一个仿京东的垂直滚动广告栏就实现了,非常简单好理解。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值