public 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;
}
}
mHeight / 2 - (bound.top + bound.bottom) / 2 //在纵坐标为mY的地方绘制文字 //计算方式 //mheight /2 = mY + (bound.top + bound.bottom) / 2 ;
mY == 0 - bound.bottom //在纵坐标为mY的地方绘制,此时文字刚好移动到最高点 //计算方式 //mY + bound.bottom = 0 ;
mY = mHeight - indexBound.top; //在纵坐标为mY的地方绘制,此时文字刚好移动到最高点 //计算方式 //mY + bound.top = mHeight ;
//初始化默认值
private void init() {
mDuration = 500;
mInterval = 1000;
mIndex = 0;
mPaintFront = new Paint();
mPaintFront.setAntiAlias(true);
mPaintFront.setDither(true);
mPaintFront.setTextSize(30);
mPaintBack = new Paint();
mPaintBack.setAntiAlias(true);
mPaintBack.setDither(true);
mPaintBack.setTextSize(30);
}
//获取当前的数据 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(); mPaintBack.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++;//换下一组数据
}
//移动到中间
if (mY == getMeasuredHeight() / 2 - (indexBound.top + indexBound.bottom) / 2) {
isMove = false;//停止移动
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
postInvalidate();//通知重绘
isMove = true;//设置移动为true
}
}, mInterval);//停顿多少毫秒之后再次移动
}
移动的处理与数据源的处理
mY -= 1;//每次只移动一个像素,尽量保证平滑显示
//循环使用数据
if (mIndex == mTexts.size()) {
mIndex = 0;
}
//如果是处于移动状态时的,则延迟绘制
//计算公式为一个比例,一个时间间隔移动组件高度,则多少毫秒来移动1像素
if (isMove) {
postInvalidateDelayed(mDuration / getMeasuredHeight());
}
至此对逻辑的处理就完成了,接下来要设置点击事件
public interface onClickLitener {
public void onClick(String mUrl);
}
private onClickLitener onClickLitener;
public void setOnClickLitener(TextViewAd.onClickLitener onClickLitener) {
this.onClickLitener = onClickLitener;
}
//重写onTouchEvent事件,并且要返回true,表明当前的点击事件由这个组件自身来处理
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//调用回调,将当前数据源的链接传出去
if (onClickLitener != null) {
onClickLitener.onClick(mTexts.get(mIndex).getmUrl());
}
break;
}
return true;
}
暴露一些其他属性的设置方式
//设置数据源
public void setmTexts(List mTexts) {
this.mTexts = mTexts;
}
//设置广告文字的停顿时间
public void setmInterval(int mInterval) {
this.mInterval = mInterval;
}
//设置文字从出现到消失的时长
public void setmDuration(int mDuration) {
this.mDuration = mDuration;
}
//设置前缀的文字颜色
public void setFrontColor(int mFrontColor) {
mPaintFront.setColor(mFrontColor);
}
//设置正文内容的颜色
public void setBackColor(int mBackColor) {
mPaintBack.setColor(mBackColor);
}
有兴趣的同学可以将这些属性设置到attrs.xml文件中然后就可以在布局文件中设置属性了,这里就不演示了,因为觉得每次copy这个View还得把xml文件也copy比较麻烦,毕竟as有自动补全,可以很方便的看到暴露在外面的方法.(个人感受而已).
贴一下完整的ADTextView的代码,方便查看
package com.qiyuan.jindongshangcheng.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
import com.qiyuan.jindongshangcheng.enity.ADEnity;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by huanghaojie on 2016/9/30.
*/
public class TextViewAd extends TextView {
private int mDuration; //文字从出现到显示消失的时间
private int mInterval; //文字停留在中间的时长切换的间隔
private List<ADEnity> mTexts; //显示文字的数据源
private int mY = 0; //文字的Y坐标
private int mIndex = 0; //当前的数据下标
private Paint mPaintBack; //绘制内容的画笔
private Paint mPaintFront; //绘制前缀的画笔
private boolean isMove = true; //文字是否移动
private String TAG = "ADTextView";
private boolean hasInit = false;//是否初始化刚进入时候文字的纵坐标
public interface onClickLitener {
public void onClick(String mUrl);
}
private onClickLitener onClickLitener;
public void setOnClickLitener(TextViewAd.onClickLitener onClickLitener) {
this.onClickLitener = onClickLitener;
}
public TextViewAd(Context context) {
this(context, null);
}
public TextViewAd(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
//重写onTouchEvent事件,并且要返回true,表明当前的点击事件由这个组件自身来处理
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
//调用回调,将当前数据源的链接传出去
if (onClickLitener != null) {
onClickLitener.onClick(mTexts.get(mIndex).getmUrl());
}
break;
}
return true;
}
//设置数据源
public void setmTexts(List mTexts) {
this.mTexts = mTexts;
}
//设置广告文字的停顿时间
public void setmInterval(int mInterval) {
this.mInterval = mInterval;
}
//设置文字从出现到消失的时长
public void setmDuration(int mDuration) {
this.mDuration = mDuration;
}
//设置前缀的文字颜色
public void setFrontColor(int mFrontColor) {
mPaintFront.setColor(mFrontColor);
}
//设置正文内容的颜色
public void setBackColor(int mBackColor) {
mPaintBack.setColor(mBackColor);
}
//初始化默认值
private void init() {
mDuration = 500;
mInterval = 1000;
mIndex = 0;
mPaintFront = new Paint();
mPaintFront.setAntiAlias(true);
mPaintFront.setDither(true);
mPaintFront.setTextSize(30);
mPaintBack = new Paint();
mPaintBack.setAntiAlias(true);
mPaintBack.setDither(true);
mPaintBack.setTextSize(30);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.i(TAG, "onSizeChanged: " + h);
}
@Override
protected void onDraw(Canvas canvas) {
if (mTexts != null) {
Log.i(TAG, "onDraw: " + mY);
//获取当前的数据
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();
mPaintBack.getTextBounds(back, 0, back.length(), contentBound);
//刚开始进入的时候文字应该是位于组件的底部的 ,但是这个值是需要获取组件的高度和当前显示文字的情况下来判断的,
// 所以应该放在onDraw内来初始化这个值,所以需要前面的是否初始化的属性,判断当mY==0并且未初始化的时候给mY赋值.
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++;//换下一组数据
}
canvas.drawText(back, 0, back.length(), (indexBound.right - indexBound.left) + 20, mY, mPaintBack);
canvas.drawText(font, 0, font.length(), 10, mY, mPaintFront);
//移动到中间
if (mY == getMeasuredHeight() / 2 - (indexBound.top + indexBound.bottom) / 2) {
isMove = false;//停止移动
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
postInvalidate();//通知重绘
isMove = true;//设置移动为true
}
}, mInterval);//停顿多少毫秒之后再次移动
}
//移动的处理与数据源的处理
mY -= 1;//每次只移动一个像素,尽量保证平滑显示
//循环使用数据
if (mIndex == mTexts.size()) {
mIndex = 0;
}
//如果是处于移动状态时的,则延迟绘制
//计算公式为一个比例,一个时间间隔移动组件高度,则多少毫秒来移动1像素
if (isMove) {
postInvalidateDelayed(mDuration / getMeasuredHeight());
}
}
}
}
怎么使用呢?
1,现在xml文件里引入这个自定义控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.qiyuan.jindongshangcheng.view.TextViewAd
android:id="@+id/textad"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
2.在MainActivity中使用
/**
* Created by huanghaojie on 2016/9/30.
*/
public class MainActivity extends Activity {
private TextViewAd textViewAd;
private List<ADEnity> mList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
textViewAd = (TextViewAd) findViewById(R.id.textad);
mList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
ADEnity adEnity = new ADEnity("前缀" + i, "后缀" + i, "http://www.baidu.com"+i);
mList.add(adEnity);
}
textViewAd.setmTexts(mList);
textViewAd.setFrontColor(Color.RED);
textViewAd.setBackColor(Color.BLUE);
textViewAd.setmDuration(1000);
textViewAd.setmInterval(1000);
textViewAd.setOnClickLitener(new TextViewAd.onClickLitener() {
@Override
public void onClick(String mUrl) {
Toast.makeText(MainActivity.this,"点击了"+mUrl,Toast.LENGTH_LONG).show();
}
});
}
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有