服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android高仿京东垂直循环滚动新闻栏

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

2021-06-30 15:32Losileeya Android

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

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

不多说看效果:

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

代码实现

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

?
1
2
3
4
5
6
7
<?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>
自定义控件的获取属性方法都一样:
?
1
2
3
4
5
6
7
//获取自定义属性
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();

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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>

布局很简单,效果呢:

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
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个条目,并且用线程控制,根据条目的下标轮流滚动显示。

具体使用代码:

初始化数据:

?
1
2
3
4
5
6
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"));
}

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

?
1
2
3
4
5
6
initdata();
final jdviewadapter adapter = new jdviewadapter(datas);
final jdadverview tbview = (jdadverview) findviewbyid(r.id.jdadver);
tbview.setadapter(adapter);
//开启线程滚东
tbview.start();

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

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

延伸 · 阅读

精彩推荐
  • AndroidAndroid实现固定屏幕显示的方法

    Android实现固定屏幕显示的方法

    这篇文章主要介绍了Android实现固定屏幕显示的方法,实例分析了Android屏幕固定显示所涉及的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    鉴客6192021-03-27
  • Android汇总Android视频录制中常见问题

    汇总Android视频录制中常见问题

    这篇文章主要汇总了Android视频录制中常见问题,帮助大家更好地解决Android视频录制中常见的问题,需要的朋友可以参考下...

    yh_thu5192021-04-28
  • AndroidAndroid实现Service获取当前位置(GPS+基站)的方法

    Android实现Service获取当前位置(GPS+基站)的方法

    这篇文章主要介绍了Android实现Service获取当前位置(GPS+基站)的方法,较为详细的分析了Service基于GPS位置的技巧,具有一定参考借鉴价值,需要的朋友可以参考下...

    Ruthless8342021-03-31
  • AndroidAndroid程序设计之AIDL实例详解

    Android程序设计之AIDL实例详解

    这篇文章主要介绍了Android程序设计的AIDL,以一个完整实例的形式较为详细的讲述了AIDL的原理及实现方法,需要的朋友可以参考下...

    Android开发网4642021-03-09
  • AndroidAndroid界面效果UI开发资料汇总(附资料包)

    Android界面效果UI开发资料汇总(附资料包)

    android ui界面设计,友好的界面会提高用户体验度;同时也增强了android ui界面设计的难度,本文提供了一些常用开发资料(有下载哦)感兴趣的朋友可以了解下...

    Android开发网4672021-01-03
  • AndroidAndroid编程解析XML方法详解(SAX,DOM与PULL)

    Android编程解析XML方法详解(SAX,DOM与PULL)

    这篇文章主要介绍了Android编程解析XML方法,结合实例形式详细分析了Android解析XML文件的常用方法与相关实现技巧,需要的朋友可以参考下...

    liuhe68810052021-05-03
  • AndroidAndroid中AsyncTask详细介绍

    Android中AsyncTask详细介绍

    这篇文章主要介绍了Android中AsyncTask详细介绍,AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合,需要的朋友可以参考下...

    Android开发网7452021-03-11
  • AndroidAndroid CardView+ViewPager实现ViewPager翻页动画的方法

    Android CardView+ViewPager实现ViewPager翻页动画的方法

    本篇文章主要介绍了Android CardView+ViewPager实现ViewPager翻页动画的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Abby代黎明9602022-03-02