效果图:

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

先看一看布局文件:

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

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

Android——仿京东垂直滚动广告栏相关推荐

  1. [Android]仿京东手机端类别页

    [Android]仿京东手机端类别页 京东手机端的类别标签页, 是一个左侧滑动可选择类别, 右侧一个类别明细的列表联动页面. 当用户选择左侧选项, 可在右侧显示更多选项来选择. 实现方式也不少. 最常 ...

  2. Android仿京东、天猫商品详情页

    前言 前面在介绍控件TabLayout控件和CoordinatorLayout使用的时候说了下实现京东.天猫详情页面的效果,今天要说的是优化版,是我们线上实现的效果,首先看一下效果: 项目结构分析 首 ...

  3. Android仿京东收货地址

    Android仿京东三级联动收货地址 1.在本地新建assets目录,存放三级联动json数据,取本地json数据作为数据源 String data = com.miles.zcstc.fingerd ...

  4. android高仿京东秒杀,Android仿京东首页秒杀倒计时

    本文实例为大家分享了Android仿京东首页秒杀倒计时的具体代码,供大家参考,具体内容如下 xml配置 android:layout_width="wrap_content" an ...

  5. android自定义视频列表,Android仿京东天猫列表页播视频看这一篇就足够了

    阅读本文解决什么问题? 解决android 滑动列表页自动播视频中的一些技术难点.助力更好的实现类似需求.不涉及到播放器的具体编解码技术,因为各家用的播放器可能都不一样(其实是我不会~) 何时播视频最 ...

  6. android京东商城一级分类到二级分类的滑动效果,Android仿京东分类模块左侧分类条目效果...

    本文实例为大家分享了Android仿京东左侧分类条目效果的具体代码,供大家参考,具体内容如下 import android.app.Activity; import android.os.Bundle ...

  7. android仿京东商城例子

    最近做android的开发,发现了一个好的工程,android仿京东商城. demo地址::http://download.csdn.net/detail/a358763471/8728155 上几张 ...

  8. android 自定义textview 垂直滚动,Android中TextView如何实现水平和垂直滚动

    一.只想让TextView显示一行,但是文字超过TextView的长度怎么办? 在开头显示省略号 android:singleLine="true" android:ellipsi ...

  9. android 仿搜索动画,Android仿京东顶部搜索框滑动伸缩动画效果

    最近使用京东发现,京东顶部的搜索框有一个新的伸缩效果,根据用户的手势滑动,伸缩搜索框.觉得效果还不错,就看了下其他的应用有没有这种伸缩的效果,发现安居客也使用了类似的一种效果,然后就想着实现这样的一种 ...

最新文章

  1. H5打开预览PDF,PPT等文件
  2. 公司虚拟化平台VMware vCenter Server无法连接故障排查解决
  3. 全网最详细的大数据集群环境下如何正确安装并配置多个不同版本的Cloudera Hue(图文详解)...
  4. 笔记-高项案例题-2014年上-计算题
  5. Vue-Cleave - 在Vue中使用CleaveJS格式化你的输入内容
  6. [转]关于sizeof()的一些思考
  7. [转]C++的Json解析库:jsoncpp和boost
  8. 智能合约最佳实践 之 Solidity 编码规范
  9. vsftpd配置虚拟用户(实战)
  10. 地球人来源2【地底爬虫人访谈】
  11. 修改判断名字重复,保证名字唯一
  12. 使用 ESP-Prog / Jlink 进行 JTAG 调试时的常见错误及解决办法
  13. 运筹系列63:使用ALNS求解大规模TSP问题
  14. 什么是本格推理?有什么推荐作品?
  15. debian 7 网络安装后无法联接wifi
  16. poodle attack
  17. SparkSteaming使用
  18. oracle fnd global,Oracle EBS R12 - 利用fnd_conc_global.set_req_globals设置子请求的Parent Request ID...
  19. 换个方式认识一下——微信公众号搜索公众号列表 API
  20. 换网站服务器需要备案吗,换服务器要重新备案吗?

热门文章

  1. 多多买菜代收被叫停?拼多多这样回应
  2. crosscheck(crosscheck是什么意思)
  3. E/WindowManager: android.view.WindowLeaked: Activity com.xxx.xxx.xxx
  4. Python爬取酷狗音乐歌手信息
  5. 计算机编码种类(ASCII/gbk/unicode/utf-8)
  6. 个人对软件工程的期望及个人目标
  7. html如何将网页分割开来,发现pdf文件页面内容太多,怎么把页面拆分开来?
  8. 春节感悟 - 快递延误的售后问题
  9. 【深度学习】VGG16--slim
  10. 嵌入式linux/鸿蒙开发板(IMX6ULL)开发(二十七)具体单板的LED驱动程序