欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android新闻广告条滚动效果

程序员文章站 2024-03-07 20:01:51
项目中需要用到类似公告栏的控件,能用的基本不支持多行显示,于是只好自己动手,苦于没有自定义过一个像样的控件,借鉴android公告条demo,实现了多行向上滚动的控件。在原...

项目中需要用到类似公告栏的控件,能用的基本不支持多行显示,于是只好自己动手,苦于没有自定义过一个像样的控件,借鉴android公告条demo,实现了多行向上滚动的控件。在原控件基础之上添加如下功能:
 •传入数据分页显示
 •添加left drawable
 •手指触摸事件处理
 •添加3d动画翻滚效果

效果图

Android新闻广告条滚动效果

源码

package com.android.view;

import android.content.context;
import android.content.res.typedarray;
import android.graphics.camera;
import android.graphics.matrix;
import android.graphics.paint;
import android.graphics.drawable.drawable;
import android.os.handler;
import android.os.looper;
import android.text.textpaint;
import android.text.textutils;
import android.util.attributeset;
import android.util.typedvalue;
import android.view.gravity;
import android.view.motionevent;
import android.view.view;
import android.view.view.onclicklistener;
import android.view.animation.accelerateinterpolator;
import android.view.animation.alphaanimation;
import android.view.animation.animation;
import android.view.animation.animationset;
import android.view.animation.transformation;
import android.view.animation.translateanimation;
import android.widget.framelayout;
import android.widget.linearlayout;
import android.widget.textview;

import com.sd2w.market.client.r;

import java.util.arraylist;
import java.util.list;

import static android.view.viewgroup.layoutparams.match_parent;
import static android.view.viewgroup.layoutparams.wrap_content;

/**
 * 公告滚动区
 *
 * @author 祁连山
 * @version 1.0
 * @date 2016-08-17
 */

public class rollingview extends framelayout implements onclicklistener {

 // 默认动画执行时间
 private static final int animation_duration = 1000;

 // 延迟滚动时间间隔
 private long mduration = 3000;
 // 字体颜色
 private int mtextcolor = 0xff000000;
 // 点击后字体颜色
 private int mclickcolor = 0xff0099ff;
 // 字体大小
 private float mtextsize = 14;
 // 行间距
 private int mtextpadding = 10;
 // 画笔
 private paint mpaint;
 // 默认每页信息数
 private int mpagesize = 3;
 // 最后一页余数
 private int muplimited = mpagesize;
 // 当前显示页码
 private int mcurrentpage = 0;
 // 总分页数
 private int mpagecount;
 // 左图片
 private int mleftdrawable;
 // 分页数据对象
 private list<linearlayout> mrollingpages;
 // 默认动画
 private animationset menteranimset;
 private animationset mexitanimset;
 private rollingrunnable mrunnable;
 private handler mhandler;
 private onitemclicklistener mclicklistener;
 // 布局参数
 private layoutparams mframeparams;
 private linearlayout.layoutparams mlinearparams;
 //menterdownanim,moutup分别构成向下翻页的进出动画
 private rotate3danimation menterdownanim;
 private rotate3danimation mexitupanim;

 //menterupanim,moutdown分别构成向下翻页的进出动画
 private rotate3danimation menterupanim;
 private rotate3danimation mexitdownanim;

 public rollingview(context context) {
  this(context, null);
 }

 public rollingview(context context, attributeset attrs) {
  super(context, attrs);
  // 从xml中获取属性
  typedarray array = getcontext().obtainstyledattributes(attrs, r.styleable.rollingview);
  mtextsize = array.getdimension(r.styleable.rollingview_textsize, mtextsize);
  mtextcolor = array.getcolor(r.styleable.rollingview_textcolor, mtextcolor);
  array.recycle();
  // 创建默认显示隐藏动画
  createenteranimation();
  createexitanimation();
  // 初始化画笔
  mpaint = new textpaint();
  // 初始化handler对象
  mhandler = new handler(looper.getmainlooper());

  menterdownanim = createanim(-90, 0, true, true);
  mexitupanim = createanim(0, 90, false, true);
  menterupanim = createanim(90, 0, true, false);
  mexitdownanim = createanim(0, -90, false, false);
 }

 private rotate3danimation createanim(float start, float end, boolean turnin, boolean turnup) {
  final rotate3danimation rotation = new rotate3danimation(start, end, turnin, turnup);
  rotation.setduration(300);
  rotation.setfillafter(false);
  rotation.setinterpolator(new accelerateinterpolator());
  return rotation;
 }

 /**
  * 设置分页大小
  *
  * @param pagesize
  */
 public void setpagesize(int pagesize) {
  this.mpagesize = this.muplimited = pagesize;
 }

 /**
  * 设置延迟时间
  *
  * @param millionseconds
  */
 public void setdelayedduration(long millionseconds) {
  this.mduration = millionseconds;
 }

 /**
  * 设置显示动画
  *
  * @param animation
  */
 public void setenteranimation(animationset animation) {
  menteranimset = animation;
 }

 /**
  * 设置隐藏动画
  *
  * @param animation
  */
 public void setexitanimation(animationset animation) {
  mexitanimset = animation;
 }

 /**
  * 设置行距
  *
  * @param padding
  */
 public void settextpadding(int padding) {
  this.mtextpadding = padding;
 }

 /**
  * 设置点击后字体颜色
  *
  * @param color
  */
 public void setclickcolor(int color) {
  this.mclickcolor = color;
 }

 /**
  * 设置左图片
  *
  * @param drawable
  */
 public void setleftdrawable(int drawable) {
  this.mleftdrawable = drawable;
 }

 /**
  * 设置点击事件
  *
  * @param clicklistener
  */
 public void setonitemclicklistener(onitemclicklistener clicklistener) {
  if (null == clicklistener) return;
  this.mclicklistener = clicklistener;
 }

 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure(widthmeasurespec, heightmeasurespec);
  // 如果是未指定大小,那么设置宽为300px
  int exceptwidth = 300;
  int exceptheight = 0;
  // 计算高度,如果将高度设置为textsize会很丑,因为文字有默认的上下边距。
  if (measurespec.getmode(heightmeasurespec) != measurespec.exactly) {
   if (mtextsize > 0) {
    mpaint.settextsize(mtextsize);
    paint.fontmetrics fontmetrics = mpaint.getfontmetrics();
    exceptheight = (int) (fontmetrics.bottom - fontmetrics.top);
   }
  }
  int width = resolvesize(exceptwidth, widthmeasurespec);
  int height = resolvesize(exceptheight, heightmeasurespec);
  setmeasureddimension(width, height);
 }

 public void setrollingtext(list<string> array) {
  if (null == array || array.isempty()) return;
  this.removeallviews();
  if (mrollingpages == null) {
   mrollingpages = new arraylist<>();
  }
  mrollingpages.clear();
  // 计算商数
  int quotient = array.size() / mpagesize;
  // 计算余数
  int remainder = array.size() % mpagesize;
  // 计算需要创建多少页
  mpagecount = remainder == 0 ? quotient : quotient + 1;
  for (int i = 0; i < mpagecount; i++) {
   // 创建一个布局
   linearlayout container = createcontainer();
   if (i == mpagecount - 1) {
    muplimited = remainder == 0 ? mpagesize : remainder;
   }
   for (int n = 0; n < muplimited; n++) {
    textview textview = createtextview(array.get(mpagesize * i + n));
    container.addview(textview);
   }
   // 添加到分页中
   mrollingpages.add(container);
   this.addview(container);
  }
  // 初始化显示第一页
  mcurrentpage = 0;
  mrollingpages.get(mcurrentpage).setvisibility(visible);
  this.setvisibility(mrollingpages.get(mcurrentpage));
 }

 /**
  * 创建页对象
  *
  * @return
  */
 private linearlayout createcontainer() {
  if (mframeparams == null) {
   mframeparams = new layoutparams(match_parent, wrap_content);
   mframeparams.gravity = gravity.center_vertical;
  }
  linearlayout container = new linearlayout(getcontext());
  container.setlayoutparams(mframeparams);
  container.setorientation(linearlayout.vertical);
  return container;
 }

 private void setvisibility(linearlayout container) {
  int count = container.getchildcount();
  for (int i = 0; i < count; i++) {
   container.getchildat(i).setvisibility(visible);
  }
 }

 /**
  * 创建页内容对象
  *
  * @param text
  * @return
  */
 private textview createtextview(string text) {
  if (mlinearparams == null) {
   mlinearparams = new linearlayout.layoutparams(wrap_content, wrap_content);
   mlinearparams.gravity = gravity.center_vertical;
  }
  textview textview = new textview(getcontext());
  textview.setlayoutparams(mlinearparams);
  textview.setsingleline();
  textview.setpadding(mtextpadding, mtextpadding, mtextpadding, mtextpadding);
  textview.setellipsize(textutils.truncateat.end);
  textview.settextcolor(mtextcolor);
  textview.setvisibility(invisible);
  textview.settext(text);
  if (mleftdrawable > 0) {
   drawable drawable = getcontext().getresources().getdrawable(mleftdrawable);
   // bitmap bitmap = bitmapfactory.decoderesource(getcontext().getresources(), mleftdrawable);
   // drawable drawable = new bitmapdrawable(getcontext().getresources(), bitmap);
   drawable.setbounds(0, 0, 10, 10);
   textview.setcompounddrawablepadding(10);
   textview.setcompounddrawables(drawable, null, null, null);
  }
  textview.setonclicklistener(this);
  // 设置字体大小
  if (mtextsize > 0) {
   textview.settextsize(typedvalue.complex_unit_px, mtextsize);
  }
  return textview;
 }

 private void createenteranimation() {
  menteranimset = new animationset(false);
  translateanimation translateanimation = new translateanimation(0, 0, 0, 0, translateanimation.relative_to_parent, 1f, translateanimation.relative_to_self, 0f);
  alphaanimation alphaanimation = new alphaanimation(0f, 1f);
  menteranimset.addanimation(translateanimation);
  menteranimset.addanimation(alphaanimation);
  menteranimset.setduration(animation_duration);
 }

 private void createexitanimation() {
  mexitanimset = new animationset(false);
  translateanimation translateanimation = new translateanimation(0, 0, 0, 0, translateanimation.relative_to_self, 0f, translateanimation.relative_to_parent, -1f);
  alphaanimation alphaanimation = new alphaanimation(1f, 0f);
  mexitanimset.addanimation(translateanimation);
  mexitanimset.addanimation(alphaanimation);
  mexitanimset.setduration(animation_duration);
 }

 @override
 public boolean ontouchevent(motionevent event) {
  int action = event.getaction();
  switch (action) {
   case motionevent.action_down:
    pause();
    break;
   case motionevent.action_move:
   case motionevent.action_up:
   case motionevent.action_cancel:
    resume();
    break;
  }
  return true;
 }

 public void resume() {
  // 只有一页时不进行切换
  if (mpagecount < 1) return;
  if (mrunnable == null) {
   mrunnable = new rollingrunnable();
  } else {
   mhandler.removecallbacks(mrunnable);
  }
  mhandler.postdelayed(mrunnable, mduration);
 }

 public void pause() {
  if (mrunnable != null) {
   mhandler.removecallbacks(mrunnable);
  }
 }

 @override
 public void onclick(view v) {
  if (null == mclicklistener) return;
  textview textview = (textview) v;
  mclicklistener.onitemclick(textview);
  textview.settextcolor(mclickcolor);
 }

 /**
  * 隐藏当前页,显示下一页任务
  */
 public class rollingrunnable implements runnable {

  @override
  public void run() {
   // 隐藏当前页
   linearlayout currentview = mrollingpages.get(mcurrentpage);
   currentview.setvisibility(invisible);
   if (mexitanimset != null) {
    currentview.startanimation(mexitanimset);// mexitupanim);
   }
   mcurrentpage++;
   if (mcurrentpage >= mpagecount) {
    mcurrentpage = 0;
   }
   // 显示下一页
   linearlayout nextview = mrollingpages.get(mcurrentpage);
   nextview.setvisibility(visible);
   setvisibility(nextview);
   if (menteranimset != null) {
    nextview.startanimation(menteranimset);// menterdownanim);
   }
   mhandler.postdelayed(this, mduration);
  }
 }

 public class rotate3danimation extends animation {
  private final float mfromdegrees;
  private final float mtodegrees;
  private final boolean mturnin;
  private final boolean mturnup;
  private float mcenterx;
  private float mcentery;
  private camera mcamera;

  public rotate3danimation(float fromdegrees, float todegrees, boolean turnin, boolean turnup) {
   mfromdegrees = fromdegrees;
   mtodegrees = todegrees;
   mturnin = turnin;
   mturnup = turnup;
  }

  @override
  public void initialize(int width, int height, int parentwidth, int parentheight) {
   super.initialize(width, height, parentwidth, parentheight);
   mcamera = new camera();
   mcentery = getheight() / 2;
   mcenterx = getwidth() / 2;
  }

  @override
  protected void applytransformation(float interpolatedtime, transformation t) {
   final float fromdegrees = mfromdegrees;
   float degrees = fromdegrees + ((mtodegrees - fromdegrees) * interpolatedtime);

   final float centerx = mcenterx;
   final float centery = mcentery;
   final camera camera = mcamera;
   final int derection = mturnup ? 1 : -1;

   final matrix matrix = t.getmatrix();

   camera.save();
   if (mturnin) {
    camera.translate(0.0f, derection * mcentery * (interpolatedtime - 1.0f), 0.0f);
   } else {
    camera.translate(0.0f, derection * mcentery * (interpolatedtime), 0.0f);
   }
   camera.rotatex(degrees);
   camera.getmatrix(matrix);
   camera.restore();

   matrix.pretranslate(-centerx, -centery);
   matrix.posttranslate(centerx, centery);
  }
 }

 public interface onitemclicklistener {
  void onitemclick(textview v);
 }
}

使用

// 初始化号外列表
list<string> haowaiarray = new arraylist<>();
haowaiarray.add("[母婴天地] 买尿不湿送婴儿手口湿巾");
haowaiarray.add("[利民商店] 满100免费配送");
haowaiarray.add("[果之家] 泰国金枕榴莲8元/kg");
haowaiarray.add("[户外运动] 户外运动专业装备搜集");
haowaiarray.add("[天天特价] 只要9.9还包邮");
haowaiarray.add("[尖端潮品] 折叠电动车");
haowaiarray.add("[黑科技] 智能vr带你装13");
haowaiarray.add("[旅行必备] 太阳能充电宝-永不断电");
// 绑定数据
mrollingview.setpagesize(4);
mrollingview.setclickcolor(0xff888888);
mrollingview.setleftdrawable(r.drawable.drawable_red_dot);
mrollingview.setrollingtext(haowaiarray);
mrollingview.setonitemclicklistener(this);

...

@override
public void onitemclick(textview v) {
 // handle item click event
}

@override
public void onresume() {
 super.onresume();
 mrollingview.resume();
}
@override
public void onpause() {
 super.onpause();
 mrollingview.pause();
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。