转载请标明出处:
http://blog.csdn.net/hai_qing_xu_kong/article/details/51013562
本文出自:【顾林海的博客】

##前言

上次在京东APP上买东西时,发现首页中间有块叫“京东快报”的栏目,其中广告条能自动向上滚动,效果还不错,看到这个效果,第一个念头就是我能不能实现,于是就诞生了这篇文章。

我们看看实现后的效果:

##实现原理

起初看到这个效果时,第一个想法就是向上移动动画+定时器,但当我准备写时发现,滚动时上下文字都是逐渐出来的(有点像滑动的),如果用动画的话不行,如果用滑动的话,那就是ListView了,但在看效果图,界面上明明只有一个ITEM,于是,我进行了以下改动:

  • 设置ListView的高度与Item高度一致,这样界面中就只显示一个Item。
  • 自动滚动,可以使用ListView的smoothScrollBy(int distance, int duration)方法,第一个参数是滚动的距离,第二个是滚动时间。
  • 自动滚动可以通过定时器,使用Handler类自带的postDelyed。
  • ListView的无限向上滚动,可以通过继承BaseAdapter类中重写的getCount()方法时返回Integer.MAX_VALUE使其接近无限大。
  • 触摸事件的拦截,可以通过onInterceptTouchEvent来实现,返回false。

注意:通过smoothScrollBy方法滚动时,由于布局中的高度时dp,但这里面的第一个参数是sp,因此需要将dp转sp,转换完毕后的是float,但方法中是需要int,这样的话有可能导致小数位的丢失,自动滚动产生偏差,可以通过setSelection(int position)方法纠正位置,在smoothScrollBy方法调用后执行setSelection方法。

##控件的使用

根据业务场景不同,如果是主页的广告条,可以创建MainScrollUpAdvertisementView类继承自BaseAutoScrollUpTextView,BaseAutoScrollUpTextView后尖括号中是广告的数据类型,这里假设是AdvertisementObject。

1、创建我们的广告类

package com.example.autoscrollup.entity;import java.io.Serializable;/*** 获取的首页广告条数据* * @author 顾林海* */
public class AdvertisementObject implements Serializable {public String title;public String info;
}

2、创建MainScrollUpAdvertisementView类继承自BaseAutoScrollUpTextView:

package com.example.autoscrollup.view;import android.content.Context;
import android.util.AttributeSet;import com.example.autoscrollup.entity.AdvertisementObject;
import com.example.autoscrollup.view.base.BaseAutoScrollUpTextView;/*** <pre>* 制作主页的向上广告滚动条* AdvertisementObject是主页的数据源,假如通过GSON或FastJson获取的实体类* * <pre>* @author 顾林海* */
public class MainScrollUpAdvertisementView extendsBaseAutoScrollUpTextView<AdvertisementObject> {public MainScrollUpAdvertisementView(Context context, AttributeSet attrs,int defStyle) {super(context, attrs, defStyle);}public MainScrollUpAdvertisementView(Context context, AttributeSet attrs) {super(context, attrs);}public MainScrollUpAdvertisementView(Context context) {super(context);}@Overridepublic String getTextTitle(AdvertisementObject data) {return data.title;}@Overridepublic String getTextInfo(AdvertisementObject data) {return data.info;}/*** 这里面的高度应该和你的xml里设置的高度一致*/@Overrideprotected int getAdertisementHeight() {return 40;}}

通过getTextTitle、getTextInfo、getAdertisementHeight方法获取标题、内容、以及整个广告条的高度。
这里面的getAdertisementHeight方法返回的高度必须与你将要创建的xml文件中MainScrollUpAdvertisementView 控件高度一致,比如上面是40,那我们创建的xml是这样的:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="10dp"android:layout_marginRight="10dp" ><ImageViewandroid:id="@+id/iv_icon"android:layout_width="wrap_content"android:layout_height="40dp"android:layout_centerVertical="true"android:src="@drawable/icon" /><com.example.autoscrollup.view.MainScrollUpAdvertisementViewandroid:id="@+id/main_advertisement_view"android:layout_width="match_parent"android:layout_height="40dp"android:layout_centerVertical="true"android:layout_marginLeft="10dp"android:layout_toRightOf="@id/iv_icon" ></com.example.autoscrollup.view.MainScrollUpAdvertisementView></RelativeLayout></RelativeLayout>

这里android:layout_height="40dp"设置为40,与我们定义的MainScrollUpAdvertisementView 类中的getAdertisementHeight方法返回的高度一致。

3、在我们的Activity中使用定义的MainScrollUpAdvertisementView 控件:

package com.example.autoscrollup;import java.util.ArrayList;import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;import com.example.autoscrollup.entity.AdvertisementObject;
import com.example.autoscrollup.view.MainScrollUpAdvertisementView;
import com.example.autoscrollup.view.base.BaseAutoScrollUpTextView.OnItemClickListener;public class MainActivity extends Activity {private MainScrollUpAdvertisementView mMainScrollUpAdvertisementView;private ArrayList<AdvertisementObject> mDataList = new ArrayList<AdvertisementObject>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initData();initViews();}/*** 模拟网络获取数据*/private void initData() {AdvertisementObject advertisementObject = new AdvertisementObject();advertisementObject.title = "爆";advertisementObject.info = "踏青零食上京东,百万零食1元秒";mDataList.add(advertisementObject);advertisementObject = new AdvertisementObject();advertisementObject.title = "公告";advertisementObject.info = "看老刘中国行,满129减50!";mDataList.add(advertisementObject);advertisementObject = new AdvertisementObject();advertisementObject.title = "爆";advertisementObject.info = "高姿CC霜全渠道新品首发,领券199减50,点击查看";mDataList.add(advertisementObject);}private void initViews() {mMainScrollUpAdvertisementView = (MainScrollUpAdvertisementView) findViewById(R.id.main_advertisement_view);mMainScrollUpAdvertisementView.setData(mDataList);mMainScrollUpAdvertisementView.setTextSize(15);mMainScrollUpAdvertisementView.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(int position) {Toast.makeText(MainActivity.this,"点击了第" + position + "个广告条", Toast.LENGTH_SHORT).show();}});mMainScrollUpAdvertisementView.setTimer(2000);mMainScrollUpAdvertisementView.start();}}

注册我们的控件,为控件添加数据通过setData方法添加网络获取到的数据。通过setTextSize设置广告条中文字的大小,通过setOnItemClickListener方法设置监听事件,通过setTimer方法设置滚动的间隔时间,最后通过start方法开启滚动。其中stop方法用于在Activity暂停或销毁时调用,上面暂未写出,请大家自行添加。

至此使用完毕,整体使用还是挺简单的。

##代码讲解

以下是对BaseAutoScrollUpTextView这个基类的说明,先贴出完整的源代码:

package com.example.autoscrollup.view.base;import java.util.ArrayList;import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;import com.example.autoscrollup.R;/*** <pre>* 京东快报 自动向上滚动的广告基类* 内部包含TextView的自动向上滚动* * <pre>* @author 顾林海* * @param <T>*/
public abstract class BaseAutoScrollUpTextView<T> extends ListView implementsAutoScrollData<T> {/*** 数据源*/private ArrayList<T> mDataList = new ArrayList<T>();/*** 字体大小*/private float mSize=16;/*** 数据总数*/private int mMax;private int position = -1;/*** 向上滚动距离*/private int scroll_Y;private int mScrollY;/*** 适配器*/private AutoScrollAdapter mAutoScrollAdapter = new AutoScrollAdapter();/*** 监听器*/private OnItemClickListener mOnItemClickListener;private long mTimer = 1000;private Context mContext;/*** 获取高度* * @return*/protected abstract int getAdertisementHeight();private Handler handler = new Handler();Runnable runnable = new Runnable() {@Overridepublic void run() {// 开启轮播switchItem();handler.postDelayed(this, mTimer);}};public interface OnItemClickListener {public void onItemClick(int position);}public BaseAutoScrollUpTextView(Context context, AttributeSet attrs,int defStyle) {super(context, attrs, defStyle);this.mContext = context;mScrollY = dip2px(getAdertisementHeight());init();}public BaseAutoScrollUpTextView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public BaseAutoScrollUpTextView(Context context) {this(context, null);}private void init() {this.setDivider(null);this.setFastScrollEnabled(false);this.setDividerHeight(0);this.setEnabled(false);}/*** dp-->px* * @param dipValue* @return*/private int dip2px(float dipValue) {final float scale = mContext.getResources().getDisplayMetrics().density;return (int) (dipValue * scale + 0.5f);}/*** 开始轮播*/private void switchItem() {if (position == -1) {scroll_Y = 0;} else {scroll_Y = mScrollY;}smoothScrollBy(scroll_Y, 2000);setSelection(position);position++;}/*** 广告条适配器* * @author 顾林海* */private class AutoScrollAdapter extends BaseAdapter {@Overridepublic int getCount() {final int count = mDataList == null ? 0 : mDataList.size();return count > 1 ? Integer.MAX_VALUE : count;}@Overridepublic Object getItem(int position) {return mDataList.get(position % mMax);}@Overridepublic long getItemId(int position) {return position % mMax;}@Overridepublic View getView(final int position, View convertView,ViewGroup parent) {ViewHolder viewHolder;if (null == convertView) {viewHolder = new ViewHolder();convertView = LayoutInflater.from(mContext).inflate(R.layout.item_layout, null);viewHolder.mTitleView = (TextView) convertView.findViewById(R.id.tv_title);viewHolder.mInfoView = (TextView) convertView.findViewById(R.id.tv_info);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}T data = mDataList.get(position % mMax);viewHolder.mTitleView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,dip2px(getAdertisementHeight())));viewHolder.mTitleView.setTextSize(mSize);viewHolder.mInfoView.setTextSize(mSize);viewHolder.mTitleView.setText(getTextTitle(data));viewHolder.mInfoView.setText(getTextInfo(data));convertView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mOnItemClickListener.onItemClick(position % mMax);}});return convertView;}}static class ViewHolder {TextView mTitleView;// 标题TextView mInfoView;// 内容}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {return false;}/*** 添加数据* * @param _datas*/public void setData(ArrayList<T> _datas) {mDataList.clear();mDataList.addAll(_datas);mMax = mDataList == null ? 0 : mDataList.size();this.setAdapter(mAutoScrollAdapter);mAutoScrollAdapter.notifyDataSetChanged();}/*** 设置文字大小* @param size*/public void setTextSize(float _size){this.mSize=_size;}/*** 设置监听事件*/public void setOnItemClickListener(OnItemClickListener _listener) {this.mOnItemClickListener = _listener;}/*** 设置轮播间隔时间* * @param _time*            毫秒单位*/public void setTimer(long _time) {this.mTimer = _time;}/*** 开启轮播*/public void start() {handler.postDelayed(runnable, 1000);}/*** 关闭轮播*/public void stop() {handler.removeCallbacks(runnable);}}

以上主要是通过Handler类自带的postDelyed实现一个定时的轮播,轮播时调用了ListView的:

smoothScrollBy(scroll_Y, 2000);
setSelection(position);

数据的回调主要是定义了一个范型接口,范型接口的具体实现延迟到子类实现,这样方便大家格局不同场景下定义不同的广告条。

最后的最后大家使用时一定要注意在xml中使用你自己定义的广告条(继承BaseAutoScrollUpTextView),高度一定要与子类getAdertisementHeight方法返回的值一致

如果大家喜欢本人的文章,请多多支持,项目地址在最下方

> 以下是完整的github项目地址,欢迎star,fork > github项目源码地址:[点击【项目源码】](https://github.com/LinhaiGu/ASUpAdvertisementArticle)

Android之高仿京东APP首页“京东快报”自动向上滚动的广告条相关推荐

  1. 仿京东首页的京东快报,自动向上滚动的广告条

    向上滚动的广告条 实现原理 起初看到这个效果时,第一个想法就是向上移动动画+定时器,但当我准备写时发现,滚动时上下文字都是逐渐出来的(有点像滑动的),如果用动画的话不行,如果用滑动的话,那就是List ...

  2. 《iVX 高仿美团APP制作移动端完整项目》01 标题需求分析思路及制作流程

    点击整个专栏查看其它系列文章 (系列文章更新中-):<iVX 高仿美团APP制作移动端完整项目> 项目界面预览: 一.创建项目 首先打开在线编辑器地址:https://editor.ivx ...

  3. android开发百度地图坐标偏差,利用百度地图Android sdk高仿微信发送位置功能及遇到的问题...

    接触了百度地图开发平台半个月了,这2天试着模仿了微信给好友发送位置功能,对百度地图的操作能力又上了一个台阶 我在实现这个功能的时候,遇到一些困难,可能也是别人将会遇到的困难,特在此列出 1.在微信发送 ...

  4. Android之高仿QQ6.6.0侧滑效果(背景动画、透明+沉浸式状态栏、渐变效果)

    根据需求实现类似QQ侧滑效果,之前看到过很多实现方式通过SlidingMenu,但是既然官方推出了自己的专属控件,那么使用DrawerLayout就是不二选择.且看下文. 一.先来看看官方文档解释 D ...

  5. 高仿微信APP实战(一)-Actionbar的制作与应用

    高仿微信APP实战(一)-Actionbar的制作与应用 本文是仿微信app实战系列的第一部分,先从简单的做起,边做边学习.从顶部actionbar开始,先看一下效果图: 一.定义主题样式 <r ...

  6. Android之高仿墨迹天气桌面组件(AppWidgetProvider) .

    Android之高仿墨迹天气桌面组件(AppWidgetProvider) . 点击:382 发布时间:2012-10-03 更多0 相信墨迹天气,大家都见过,他在时间显示和天气界面上,很吸引人,今天 ...

  7. 《iVX 高仿美团APP制作移动端完整项目》04 美食页 标题、搜索、商家标题制作

    点击整个专栏查看其它系列文章 (系列文章更新中-):<iVX 高仿美团APP制作移动端完整项目> 项目界面预览: 一.美食页顶部商家页制作 1.1 页面主格调确认 该美食页为首页中美食按钮 ...

  8. 《iVX 高仿美团APP制作移动端完整项目》03 推介信息及推荐商家分析及制作

    点击整个专栏查看其它系列文章 (系列文章更新中-):<iVX 高仿美团APP制作移动端完整项目> 项目界面预览: 一.推荐信息制作 推荐信息与之前的标题下推荐信息制作类似: 此时依旧创建一 ...

  9. 《iVX 高仿美团APP制作移动端完整项目》02 搜索、搜索提示及类别需求分析思路及制作流程

    点击整个专栏查看其它系列文章 (系列文章更新中-):<iVX 高仿美团APP制作移动端完整项目> 项目界面预览: 一.搜索制作 在上一节中我们完成了标题头的制作,接下来我们查看如何制作搜索 ...

最新文章

  1. 使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?(非常稳定、捕获所有异常、非常适合从头开始,但大公司已经有现成的C++框架、所以不会使用)
  2. apache php value,apache-2.2 – 错误启动Apache“php value”
  3. 异常处理python要求输入的为英文_python(异常处理)
  4. jQuery笔记——选择器
  5. easyexcel 日期类型 convert_[Oracle 专题] SQL 日期、数字、字符串,运算、转换
  6. 腾讯否认“PC端QQ秀下线”:只是在聊天窗口被折叠
  7. 关于2022年度深圳市技术攻关重大项目的申报通知
  8. 利用DMRMAN备份时出现“管道连接失败”的错误信息的解决方法
  9. pygame之surface
  10. 思维模型:建立高品质思维的30种模型
  11. 抖音创作者信用分:如何提升信用等级,获取更多机会
  12. 忘记历史就意味着背叛
  13. 中考计算机必背知识点,语文中考必背知识考点(完整版)
  14. php接入钉钉注册回调
  15. 水星路由器wan口ip显示0_路由器wan口ip地址显示0.0.0.0怎么办
  16. 手机控制树莓派linux,使用安卓手机控制树莓派
  17. 上海交大陈海波教授、夏虞斌教授领衔巨作上市:《操作系统:原理与实现》
  18. 阿里 - 淘宝 - 精排模型发展趋势
  19. 【立创开源】N32G430C8L7最小系统板
  20. 目前最新2018传智播客黑马训练营JAVAEE49期培训项目实战(完整)

热门文章

  1. 程序员:必备技能 Git
  2. Unix/Linux fork后传-clone
  3. porta rch_Smeerch.it
  4. Farey sequences
  5. CPC广告业务架构总结
  6. eclipse的web工程中导入jir包如何放到lib目录中
  7. weexpack 的 Login.vue 及 vue 的 Login.vue
  8. 可由线性表示且表达式唯一_证明y可由b1.b2--bn线性表出且表示法唯一
  9. 技术分享 | Slow Query Log 使用详解
  10. 100个python算法超详细讲解:邮票组合