Android高仿京东垂直循环滚动新闻栏

实现思路其实很简单,就是一个自定义的LinearLayout,并且textView能够循环垂直滚动,而且条目可以点击,显示区域最多显示2个条目,并且还有交替的属性垂直移动的动画效果,通过线程来控制滚动的实现。

不多说看效果:

代码实现

我们先来为控件设置自定义属性:

<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="JDAdverView"> <attr name="gap" format="integer" /> <attr name="animDuration" format="integer"/> </declare-styleable> </resources> 自定义控件的获取属性方法都一样: //获取自定义属性 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.JDAdverView); mAdverHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, jdAdverHeight, getResources().getDisplayMetrics()); int gap = array.getInteger(R.styleable.JDAdverView_gap, mGap); int animDuration = array.getInteger(R.styleable.JDAdverView_animDuration, mAnimDuration); //关闭清空TypedArray,防止内存泄露 array.recycle();

然后呢,我们来看一下条目的布局:

<?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="60dp" android:background="#ffffff" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:id="@+id/tag" android:textColor="#ff0000" android:layout_marginLeft="10dp" android:text="最新" android:background="@drawable/corner" android:textSize="18sp" android:padding="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/title" android:layout_marginLeft="10dp" android:singleLine="true" android:ellipsize="end" android:textSize="20sp" android:text="价格惊呆!电信千兆光纤上市" android:textColor="#000000" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>

布局很简单,效果呢:

不解释,我们来写适配器了:

package com.example.jdadvernotice; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.example.jdadvernotice.entity.AdverNotice; import com.example.jdadvernotice.view.JDAdverView; import java.util.List; /** * Created by Administrator on 2016/3/20. * 京东广告栏数据适配器 * */ public class JDViewAdapter { private List<AdverNotice> mDatas; public JDViewAdapter(List<AdverNotice> mDatas) { this.mDatas = mDatas; if (mDatas == null || mDatas.isEmpty()) { throw new RuntimeException("nothing to show"); } } /** * 获取数据的条数 * @return */ public int getCount() { return mDatas == null ? 0 : mDatas.size(); } /** * 获取摸个数据 * @param position * @return */ public AdverNotice getItem(int position) { return mDatas.get(position); } /** * 获取条目布局 * @param parent * @return */ public View getView(JDAdverView parent) { return LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null); } /** * 条目数据适配 * @param view * @param data */ public void setItem(final View view, final AdverNotice data) { TextView tv = (TextView) view.findViewById(R.id.title); tv.setText(data.title); TextView tag = (TextView) view.findViewById(R.id.tag); tag.setText(data.url); //你可以增加点击事件 view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //比如打开url Toast.makeText(view.getContext(), data.url, Toast.LENGTH_SHORT).show(); } }); } }

然后我们就来自定义view:

package com.example.jdadvernotice.view; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.widget.LinearLayout; import com.example.jdadvernotice.JDViewAdapter; import com.example.jdadvernotice.R; /** * Created by zengyu on 2016/3/20. */ public class JDAdverView extends LinearLayout { //控件高度 private float mAdverHeight = 0f; //间隔时间 private final int mGap = 4000; //动画间隔时间 private final int mAnimDuration = 1000; //显示文字的尺寸 private final float TEXTSIZE = 20f; private JDViewAdapter mAdapter; private final float jdAdverHeight = 50; //显示的view private View mFirstView; private View mSecondView; //播放的下标 private int mPosition; //线程的标识 private boolean isStarted; //画笔 private Paint mPaint; public JDAdverView(Context context) { this(context, null); } public JDAdverView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public JDAdverView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs, defStyleAttr); } /** * 初始化属性 * @param context * @param attrs * @param defStyleAttr */ private void init(Context context, AttributeSet attrs, int defStyleAttr) { //设置为垂直方向 setOrientation(VERTICAL); //抗锯齿效果 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //获取自定义属性 TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.JDAdverView); mAdverHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, jdAdverHeight, getResources().getDisplayMetrics()); int gap = array.getInteger(R.styleable.JDAdverView_gap, mGap); int animDuration = array.getInteger(R.styleable.JDAdverView_animDuration, mAnimDuration); if (mGap <= mAnimDuration) { gap = mGap; animDuration = mAnimDuration; } //关闭清空TypedArray array.recycle(); } /** * 设置数据 */ public void setAdapter(JDViewAdapter adapter) { this.mAdapter = adapter; setupAdapter(); } /** * 开启线程 */ public void start() { if (!isStarted && mAdapter.getCount() > 1) { isStarted = true; postDelayed(mRunnable, mGap);//间隔mgap刷新一次UI } } /** * 暂停滚动 */ public void stop() { //移除handle更新 removeCallbacks(mRunnable); //暂停线程 isStarted = false; } /** * 设置数据适配 */ private void setupAdapter() { //移除所有view removeAllViews(); //只有一条数据,不滚东 if (mAdapter.getCount() == 1) { mFirstView = mAdapter.getView(this); mAdapter.setItem(mFirstView, mAdapter.getItem(0)); addView(mFirstView); } else { //多个数据 mFirstView = mAdapter.getView(this); mSecondView = mAdapter.getView(this); mAdapter.setItem(mFirstView, mAdapter.getItem(0)); mAdapter.setItem(mSecondView, mAdapter.getItem(1)); //把2个添加到此控件里 addView(mFirstView); addView(mSecondView); mPosition = 1; isStarted = false; } } /** * 测量控件的宽高 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (LayoutParams.WRAP_CONTENT == getLayoutParams().height) { getLayoutParams().height = (int) mAdverHeight; } else { mAdverHeight = getHeight(); } if (mFirstView != null) { mFirstView.getLayoutParams().height = (int) mAdverHeight; } if (mSecondView != null) { mSecondView.getLayoutParams().height = (int) mAdverHeight; } } /** * 画布局 * * @param canvas */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.WHITE); mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, TEXTSIZE, getResources().getDisplayMetrics())); mPaint.setStyle(Paint.Style.STROKE); canvas.drawText("瑞士维氏军刀", TEXTSIZE, getHeight() * 2 / 3, mPaint);//写文字2/3的高度 } /** * 垂直滚蛋 */ private void performSwitch() { //属性动画控制控件滚动,y轴方向移动 ObjectAnimator animator1 = ObjectAnimator.ofFloat(mFirstView, "translationY", mFirstView.getTranslationY() - mAdverHeight); ObjectAnimator animator2 = ObjectAnimator.ofFloat(mSecondView, "translationY", mSecondView.getTranslationY() - mAdverHeight); //动画集 AnimatorSet set = new AnimatorSet(); set.playTogether(animator1, animator2);//2个动画一起 set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {//动画结束 mFirstView.setTranslationY(0); mSecondView.setTranslationY(0); View removedView = getChildAt(0);//获得第一个子布局 mPosition++; //设置显示的布局 mAdapter.setItem(removedView, mAdapter.getItem(mPosition % mAdapter.getCount())); //移除前一个view removeView(removedView); //添加下一个view addView(removedView, 1); } }); set.setDuration(mAnimDuration);//持续时间 set.start();//开启动画 } private AnimRunnable mRunnable = new AnimRunnable(); private class AnimRunnable implements Runnable { @Override public void run() { performSwitch(); postDelayed(this, mGap); } } /** * 销毁View的时候调用 */ @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); //停止滚动 stop(); } /** * 屏幕 旋转 * * @param newConfig */ @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } }

从上面可以看出,控件最多可以显示2个条目,并且用线程控制,根据条目的下标轮流滚动显示。

具体使用代码:

初始化数据:

private void initData() { datas.add(new AdverNotice("瑞士维氏军刀 新品满200-50","最新")); datas.add(new AdverNotice("家居家装焕新季,讲199减100!","最火爆")); datas.add(new AdverNotice("带上相机去春游,尼康低至477","HOT")); datas.add(new AdverNotice("价格惊呆!电信千兆光纤上市","new")); }

绑定适配器开启滚动线程:

initData(); final JDViewAdapter adapter = new JDViewAdapter(datas); final JDAdverView tbView = (JDAdverView) findViewById(R.id.jdadver); tbView.setAdapter(adapter); //开启线程滚东 tbView.start();

就写到这里吧,很晚了睡觉,欢迎大家前来拍砖。

以上内容是针对Android高仿京东垂直循环滚动新闻栏的全部介绍,希望对大家以上帮助!

时间: 2024-09-11 20:44:29

Android高仿京东垂直循环滚动新闻栏的相关文章

Android高仿京东垂直循环滚动新闻栏_Android

实现思路其实很简单,就是一个自定义的LinearLayout,并且textView能够循环垂直滚动,而且条目可以点击,显示区域最多显示2个条目,并且还有交替的属性垂直移动的动画效果,通过线程来控制滚动的实现. 不多说看效果: 代码实现 我们先来为控件设置自定义属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="JDAdv

android 高仿京东

android 高仿京东源码,两年前的作品,最近发现一些老代码,发布出来给初学者学习,下面附上几张展示的效果,有需要的请到下面地址下载,记得stare哦 https://github.com/xiangzhihong/jdProduct

android高仿今日头条 --新闻阅读器

开发流程 第一篇:(android高仿系列)今日头条 --新闻阅读器 (一) 涉及到的知识点有 1.slidingmenu.lib  (侧拉菜单包)   使用方法配置以及下载:点击这里   实现:客户端中左右2边侧拉菜单 2.命名规范可以参考:android命名规范   实现:源码中包.类.方法名称的统一 3.如何反编译:反编译就这么简单   实现:客户端中资源文件的获取 4.Fragment以及HorizontalScrollView的使用,以及重写HorizontalScrollView  

Android中使用TextView实现高仿京东淘宝各种倒计时效果_Android

今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始

Android中使用TextView实现高仿京东淘宝各种倒计时效果

今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始

Android实现仿gallery垂直滚动的效果

Android实现仿gallery垂直滚动的效果  效果图:  附件里是整个工程,如果喜欢可以下载看下.我感觉挺复杂的,如果需要的时候可以研究下,哈哈 实现垂直滚动的gallery.rar

Android高仿微信表情输入与键盘输入详解_Android

       最近公司在项目上要使用到表情与键盘的切换输入,自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个相当困扰我,不过所幸在Github(其中一个不错的开源项目,其代码整体结构很不错)并且在论坛上找些解决方案,再加上我也是研究了好多个开源项目的代码,最后才苦逼地整合出比较不错的实现效果,可以说跟微信基本一样(嘿嘿,只能说目前还没发现大Bug,若发现大家一起日后慢慢完善,这里我也只是给出了实现方案,拓展其他表情我并没有实现哈,不过代码中我实现了一个可拓展的fragme

Android 高仿斗鱼滑动验证码_Android

如下图.在Android上实现起来就不太容易,有些效果还是不如web端酷炫.) 我们的Demo,Ac娘镇楼 (图很渣,也忽略底下的SeekBar,这不是重点) 一些动画,效果录不出来了,大家可以去斗鱼web端看一下,然后下载Demo看一下,效果还是可以的. 代码 传送门: https://github.com/mcxtzhang/SwipeCaptcha 我们的Demo和web端基本上一样. 那么本控件包含不仅包含以下功能: 随机区域起点(左上角x,y)生成一个验证码阴影.验证码拼图 凹凸图形会

Android 高仿斗鱼滑动验证码

如下图.在Android上实现起来就不太容易,有些效果还是不如web端酷炫.) 我们的Demo,Ac娘镇楼 (图很渣,也忽略底下的SeekBar,这不是重点) 一些动画,效果录不出来了,大家可以去斗鱼web端看一下,然后下载Demo看一下,效果还是可以的. 代码 传送门: https://github.com/mcxtzhang/SwipeCaptcha 我们的Demo和web端基本上一样. 那么本控件包含不仅包含以下功能: 随机区域起点(左上角x,y)生成一个验证码阴影.验证码拼图 凹凸图形会