本文实例为大家分享了自定义view实现了类似百度手机助手,首页评论滚动效果。
看效果:
gif做的不好,其效果就是:几个viewitem不停的向上滚动,新加入item有个淡入的效果。
说下实现思路:自定义view继承至LinearLayout,控制item数量及其动画效果,实现item复用,传入数据即可,使用方便。
代码:
复制代码
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269/** * Jiantao.Yang * * @description 仿百度手机助手,评论滚动效果 * @time 2015/1/16 17:37 */ public class ViewFlipper extends LinearLayout { private final int MAX_SHOW_ITEM_SIZE = 5; private IAdapter mIAdapter; private int mCount; //最后一个item动画 private Animation mLastOneAnimation; //其它item动画 private Animation mCommonAnimation; //数据下标 private int mCurrentIndex; /** * 这里动画时间是1600毫秒,所以间隔得大于动画时间 */ private static final int DEFAULT_INTERVAL = 2000; private int mFlipInterval = DEFAULT_INTERVAL; private boolean mAutoStart = false; private boolean mRunning = false; private boolean mStarted = false; private boolean mVisible = false; private boolean mUserPresent = true; public ViewFlipper(Context context) { super(context); init(context); } public ViewFlipper(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public ViewFlipper(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (Intent.ACTION_SCREEN_OFF.equals(action)) { mUserPresent = false; updateRunning(); } else if (Intent.ACTION_USER_PRESENT.equals(action)) { mUserPresent = true; updateRunning(false); } } }; @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // Listen for broadcasts related to user-presence final IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); // OK, this is gross but needed. This class is supported by the // remote views machanism and as a part of that the remote views // can be inflated by a context for another user without the app // having interact users permission - just for loading resources. // For exmaple, when adding widgets from a user profile to the // home screen. Therefore, we register the receiver as the current // user not the one the context is for. getContext().registerReceiver(mReceiver, filter); if (mAutoStart) { // Automatically start when requested startFlipping(); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mVisible = false; getContext().unregisterReceiver(mReceiver); updateRunning(); } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); mVisible = visibility == VISIBLE; updateRunning(mVisible); // updateRunning(false); } private void init(Context context) { this.setOrientation(LinearLayout.VERTICAL); } public void setIAdapter(IAdapter iAdapter) { this.mIAdapter = iAdapter; initShowItems(); } public void startFlipping() { mStarted = true; updateRunning(); } public void stopFlipping() { mStarted = false; updateRunning(); } private void updateRunning() { updateRunning(true); } /** * Returns true if the child views are flipping. */ public boolean isFlipping() { return mStarted; } /** * Set if this view automatically calls {@link #startFlipping()} when it * becomes attached to a window. */ public void setAutoStart(boolean autoStart) { mAutoStart = autoStart; } /** * Returns true if this view automatically calls {@link #startFlipping()} * when it becomes attached to a window. */ public boolean isAutoStart() { return mAutoStart; } @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); event.setClassName(ViewFlipper.class.getName()); } @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(ViewFlipper.class.getName()); } /** * 初始化childViews */ private void initShowItems() { if (mIAdapter != null) { mCount = mIAdapter.getCount(); for (int i = 0; i < mCount; i++) { if (i == MAX_SHOW_ITEM_SIZE) { break; } View convertView = getChildAt(i); View item = mIAdapter.getItemView(convertView, i); addView(item, i); } } } /** * Internal method to start or stop dispatching flip {@link android.os.Message} based * on {@link #mRunning} and {@link #mVisible} state. * * @param flipNow Determines whether or not to execute the animation now, in * addition to queuing future flips. If omitted, defaults to * true. */ private void updateRunning(boolean flipNow) { boolean running = mVisible && mStarted && mUserPresent; System.out.println(" updateRunning running:" + running + " mVisible " + mVisible + " userPresent " + mUserPresent); if (running != mRunning) { if (running && (mCount > MAX_SHOW_ITEM_SIZE)) { showItems(mCurrentIndex++, flipNow); Message msg = mHandler.obtainMessage(FLIP_MSG); mHandler.sendMessageDelayed(msg, mFlipInterval); } else { mHandler.removeMessages(FLIP_MSG); } mRunning = running; } } private void showItems(final int position, boolean animate) { if (animate && (mLastOneAnimation == null || mCommonAnimation == null)) { mLastOneAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.lastone_anim); mCommonAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.common_anim); } int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); child.clearAnimation(); int index = position + i; child = mIAdapter.getItemView(child, (index >= mIAdapter.getCount()) ? (index - mIAdapter.getCount()) : index); if (animate) { if (i == childCount - 1) { child.setAnimation(mLastOneAnimation); } else { child.setAnimation(mCommonAnimation); } } child.setVisibility(View.VISIBLE); } if (animate) { mCommonAnimation.startNow(); mLastOneAnimation.startNow(); } //保证传入的position小于getCount if (mCurrentIndex >= mIAdapter.getCount()) { mCurrentIndex = 0; } } private final int FLIP_MSG = 1; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == FLIP_MSG) { if (mRunning) { showItems(mCurrentIndex++, true); msg = obtainMessage(FLIP_MSG); sendMessageDelayed(msg, mFlipInterval); } } } }; public interface IAdapter { /** * @param convertView * @param position * @return */ public View getItemView(View convertView, int position); /** * @return 数据count */ public int getCount(); } }
再来看看调用部分:
复制代码
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
37public class MainActivity extends ActionBarActivity implements ViewFlipper.IAdapter { ViewFlipper viewFlipper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewFlipper = (ViewFlipper) findViewById(R.id.view_flipper); viewFlipper.setIAdapter(this); } @Override protected void onResume() { super.onResume(); viewFlipper.startFlipping(); } @Override public View getItemView(View convertView, int position) { View item = null; TextView textView; if (convertView == null) { item = View.inflate(this, R.layout.item, null); } else { item = convertView; } textView = (TextView) item.findViewById(R.id.textview); textView.setText("测试数据:" + position); return item; } @Override public int getCount() { return 8; } }
可以看出,MainActivity实现了ViewFlipper.IAdapter接口,setAdapter后调用startFlipper即可。
这里布局文件我就不贴出来了,附上工程源码,项目里动画时间有点长,修改下就ok。
限于水平有限,不足之处难免,望各位不舍指正,与君共勉。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持靠谱客。
最后
以上就是英俊香菇最近收集整理的关于Android自定义ViewFlipper实现滚动效果的全部内容,更多相关Android自定义ViewFlipper实现滚动效果内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复