在ListView中实现顶部和底部内容指示器
来源:互联网 发布:我的网络 编辑:程序博客网 时间:2024/04/19 09:11
http://www.open-open.com/lib/view/open1324995841233.html
顶部指示器?
这是什么?
好吧,我承认这是我自己想出来的词,因为我不知道它有什么学名,究竟是什么呢?看下这个图就知道了。
这是我们的美工MM画的,偶的神呐,这虽然很漂亮,不过也让人头疼,这个箭头应该在滚到顶部的时候消失,滚下来的时候(即有条目隐藏的时候)才显示,类似的底部指示器也要有这样的效果。事实上默认的ListView和ScrollView都已经有了类似的效果,在顶部或底部还有更多内容时,会有部分渐变虚化的效果,不过美工已经设计了这样的效果,那么我们就来做吧。
出于省事的目的,本教程中的例子会基于上一篇教程来修改,主要是添加1个继承自ListView的类,以及修改布局定义文件。
ArrowListView控件的编写
001
package
net.learningandroid.lib.view;
002
003
import
net.learningandroid.lib.R;
004
import
android.content.Context;
005
import
android.graphics.Bitmap;
006
import
android.graphics.Canvas;
007
import
android.graphics.Paint;
008
import
android.graphics.Rect;
009
import
android.graphics.drawable.BitmapDrawable;
010
import
android.util.AttributeSet;
011
import
android.util.Log;
012
import
android.view.View;
013
import
android.widget.ListView;
014
015
/**
016
* 支持上下箭头的ListView
017
*
018
* <a class="referer" href="http://my.oschina.net/arthor" target="_blank">@author</a> Mr. Lu
019
*/
020
public
class
ArrowListView
extends
ListView {
021
022
private
final
float
scale = getContext().getResources().getDisplayMetrics().density;
023
private
float
topArrowPadding;
024
private
float
bottomArrowPadding;
025
026
private
static
float
DEFAULT_TOP_PADDING_DP =
2
.0f;
027
private
static
float
DEFAULT_BOTTOM_PADDING_DP =
2
.0f;
028
029
public
ArrowListView(Context context, AttributeSet attrs) {
030
super
(context, attrs);
031
032
String strTopArrowPadding = attrs.getAttributeValue(
null
,
033
"topArrowPadding"
);
034
String strBottomArrowPadding = attrs.getAttributeValue(
null
,
035
"bottomArrowPadding"
);
036
037
topArrowPadding = convertDisplayUom(strTopArrowPadding,
038
DEFAULT_TOP_PADDING_DP);
039
bottomArrowPadding = convertDisplayUom(strBottomArrowPadding,
040
DEFAULT_BOTTOM_PADDING_DP);
041
042
Log.v(
"ArrowListView"
, String.valueOf(topArrowPadding));
043
}
044
045
/**
046
* 单位转换
047
*/
048
private
float
convertDisplayUom(String sour,
float
defaultValue) {
049
try
{
050
if
(sour.toLowerCase().endsWith(
"px"
)) {
051
return
Float.parseFloat(sour.toLowerCase().replace(
"px"
,
""
));
052
}
else
if
(sour.toLowerCase().endsWith(
"dp"
)) {
053
return
Integer.parseInt(sour.toLowerCase().replace(
"dp"
,
054
""
))
055
* scale +
0
.5f;
056
}
057
}
catch
(Exception e) {
058
}
059
060
return
(defaultValue * scale +
0
.5f);
061
}
062
063
/**
064
* onDraw方法,根据ListView滚动位置绘出箭头.
065
*/
066
@Override
067
protected
void
onDraw(Canvas canvas) {
068
super
.onDraw(canvas);
069
Paint paint =
new
Paint();
070
071
// 取得箭头的图片,此处是固定图片,其实上可以做成配置方式
072
Bitmap topPic = ((BitmapDrawable) getResources().getDrawable(
073
R.drawable.arrow_up)).getBitmap();
074
Bitmap bottomPic = ((BitmapDrawable) getResources().getDrawable(
075
R.drawable.arrow_down)).getBitmap();
076
077
// 取得ListView的绘制区域大小
078
Rect r =
new
Rect();
079
this
.getDrawingRect(r);
080
081
// 计算箭头的绘制位置
082
float
top = r.top + topArrowPadding;
083
float
bottom = r.bottom - bottomArrowPadding - bottomPic.getHeight();
084
float
left = r.left + (r.right - r.left - topPic.getWidth()) /
2
;
085
086
// 计算是否需要绘制
087
boolean
drawTop =
false
;
088
boolean
drawBottom =
false
;
089
090
if
(
this
.getChildCount() >
0
) {
091
Rect rTop =
new
Rect();
092
this
.getChildAt(
0
).getLocalVisibleRect(rTop);
093
Rect rBottom =
new
Rect();
094
View lastChild =
this
.getChildAt(
this
.getChildCount() -
1
);
095
lastChild.getLocalVisibleRect(rBottom);
096
097
drawTop = (
this
.getFirstVisiblePosition() >
0
||
this
098
.getFirstVisiblePosition() ==
0
099
&& rTop.top >
0
);
100
drawBottom = (
this
.getLastVisiblePosition() <
this
.getAdapter()
101
.getCount() -
1
||
this
.getLastVisiblePosition() ==
this
102
.getAdapter().getCount() -
1
103
&& rBottom.bottom < lastChild.getHeight());
104
}
105
// 绘出箭头
106
if
(drawTop) {
107
canvas.drawBitmap(topPic, left, top, paint);
108
}
109
110
if
(drawBottom) {
111
canvas.drawBitmap(bottomPic, left, bottom, paint);
112
}
113
}
114
}
就要点解释一下上面这段代码:
注意构造方法,我们必须继承public ArrowListView(Context context, AttributeSet attrs),这样才可以让这个类在xml定义文件中使用。
还要注意到,这里用了attrs.getAttributeValue来读取XML定义文件中的属性,其实有更好的方法,容我下次再讲解,这里先偷个懒。
convertDisplayUom方法是用来将dp转换成px的,可以看到由于我们用了getAttributeValue的方式,所以需要手动将String转成Float,很麻烦。
最后就是onDraw啦,计算出画箭头的位置,画出来就行了。
接下来就是布局文件的编写了
ArrowListView在XML文件中的使用
01
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
02
<
LinearLayout
03
xmlns:android
=
"http://schemas.android.com/apk/res/android"
04
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
05
06
android:orientation
=
"vertical"
07
>
08
<
TextView
09
android:text
=
"Arrow List View Sample"
10
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
11
12
/>
13
<
net.learningandroid.lib.view.ArrowListView
14
android:id
=
"@+id/arrowListView"
15
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
16
android:paddingTop
=
"15dp"
android:paddingBottom
=
"20dp"
17
18
android:layout_margin
=
"10dp"
19
android:background
=
"@drawable/float_panel"
20
android:layout_weight
=
"1"
21
android:cacheColorHint
=
"#FFEDEDED"
android:divider
=
"#00EDEDED"
22
23
topArrowPadding
=
"5dp"
bottomArrowPadding
=
"10dp"
24
/>
25
</
LinearLayout
>
这里需要注意的是自定义控件和其中的属性的写法,不再是ListView了,而是你自己编写的控件类的类名。其它的内容就是定义padding,background,以及取消了分隔线的显示。
用这个布局文件替代上一篇教程中的布局文件,但Adapter的定义不变,因为ArrowListView是继承自ListView的,所以原先的Adapter的使用是一样的。
最后我们来看下效果:
如何?只需要小心的调整ListView的Padding和ArrowPadding的值就可以控制箭头出现的位置,如果需要控制更多,比如更换图片,或者当顶部无内容时让箭头变暗、有内容时变亮,都可以用同样的方法。
并且,如果修改了Attribute的读取方法之后,还可以通过xml文件来指定箭头的图片。
- 在ListView中实现顶部和底部内容指示器
- 在ListView中实现顶部和底部内容指示器
- 在ListView中实现顶部和底部内容指示器
- 在ListView中实现顶部和底部内容指示器
- 进阶:在ListView中实现顶部和底部的箭头
- listView从底部回到顶部代码实现
- android 的ListView中,如何判断其内容已滚动到最顶部或者最底部?
- android 的ListView中,如何判断其内容已滚动到最顶部或者最底部
- android 的ListView中,如何判断其内容已滚动到最顶部、底部
- android 的ListView中,如何判断其内容已滚动到最顶部或者最底部?
- Android的ListView中判断其内容已滚动到最顶部或者最底部
- 判断listview滑到顶部和底部
- listview 顶部添加和底部添加。
- listView滑动到底部和顶部
- 当滑动到顶部和底部时,实现Item的分离效果的ListView
- Android中判断listview是否滑动到顶部和底部方法
- 简单实现顶部和底部工具栏
- Android回到底部和返回顶部实现
- CodeForces 320 B. Ping-Pong DFS BFS 弗洛伊德算法
- 表单中什么按钮会提交,什么不会
- 黑马程序员Java基础加强
- 想做媒体公司,同时瞄准数据的LinkedIn针对企业用户全面升级页面监测功能
- 子窗体与父窗体传值操作的js示例
- 在ListView中实现顶部和底部内容指示器
- 不能上网--只要四步判断出故障所在
- 理解软件架构
- iOS设计模式——单例模式
- 模块module的运用
- 整型常量数据 下划线分隔符
- 在oracle 11g r2中要使用ASM,是不是一定要安装Grid Infrastructure?【基本问题解惑】
- 找出二叉树上任意两个结点的最近共同父结点。
- GOLDENGATE DML单向同步