热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android新闻广告条滚动效果

这篇文章主要为大家详细介绍了Android新闻广告条滚动效果的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

效果图

源码

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 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 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 &#63; quotient : quotient + 1;
  for (int i = 0; i  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 &#63; 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 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();
}

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


推荐阅读
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 本文介绍了Android开发中Intent的基本概念及其在不同Activity之间的数据传递方式,详细展示了如何通过Intent实现Activity间的跳转和数据传输。 ... [详细]
  • 优化 Android 按钮状态下的背景和文本颜色变化
    本文介绍如何通过 Android 的 Selector 实现按钮在不同状态下(如按压)的背景和文本颜色动态变化。我们将详细讲解实现步骤,并提供完整的代码示例。 ... [详细]
  • 本文详细介绍超文本标记语言(HTML)的基本概念与语法结构。HTML是构建网页的核心语言,通过标记标签描述页面内容,帮助开发者创建结构化、语义化的Web页面。 ... [详细]
  • MATLAB实现n条线段交点计算
    本文介绍了一种通过逐对比较线段来求解交点的简单算法。此外,还提到了一种基于排序的方法,但该方法较为复杂,尚未完全理解。文中详细描述了如何根据线段端点求交点,并判断交点是否在线段上。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文探讨了在Windows Server 2008环境下配置Tomcat使用80端口时遇到的问题,包括端口被占用、多项目访问失败等,并提供详细的解决方法和配置建议。 ... [详细]
  • 本文详细介绍了Java Web应用程序中的过滤器(Filter)功能,包括其作用、实现方式及配置方法。过滤器可以在请求到达目标资源之前对其进行预处理,并在响应返回给客户端之前进行后处理。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
  • 分享一个简化版的Silverlight链接图项目:Link Map Simplified
    本文介绍了一个使用Silverlight开发的可视化工具,主要用于展示和操作复杂的实体关系图(Graph)。该工具在犯罪调查系统中得到了广泛应用,帮助用户直观地获取和理解相关信息。 ... [详细]
  • 探讨如何从数据库中按分组获取最大N条记录的方法,并分享新年祝福。本文提供多种解决方案,适用于不同数据库系统,如MySQL、Oracle等。 ... [详细]
  • 本文介绍了ArcXML配置文件的分类及其在不同服务中的应用,详细解释了地图配置文件的结构和功能,包括其在Image Service、Feature Service以及ArcMap Server中的使用方法。 ... [详细]
  • 本文详细介绍如何利用已搭建的LAMP(Linux、Apache、MySQL、PHP)环境,快速创建一个基于WordPress的内容管理系统(CMS)。WordPress是一款流行的开源博客平台,适用于个人或小型团队使用。 ... [详细]
author-avatar
huangyong黄勇_513
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有