`

进阶:在ListView中实现顶部和底部的箭头

阅读更多



这是我们的美工MM画的,偶的神呐,这虽然很漂亮,不过也让人头疼,这个箭头应该在滚到顶部的时候消失,滚下来的时候(即有条目隐藏的时候)才显示,类似的底部指示器也要有这样的效果。事实上默认的ListView和ScrollView都已经有了类似的效果,在顶部或底部还有更多内容时,会有部分渐变虚化的效果,不过美工已经设计了这样的效果,那么我们就来做吧。
出于省事的目的,本教程中的例子会基于上一篇教程来修改,主要是添加1个继承自ListView的类,以及修改布局定义文件。

ArrowListView控件的编写:
import net.learningandroid.lib.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
 
/**
 * 支持上下箭头的ListView
 * 
 * @author Mr. Lu
 */
public class ArrowListView extends ListView {
 
	private final float scale = getContext().getResources().getDisplayMetrics().density;
	private float topArrowPadding;
	private float bottomArrowPadding;
 
	private static float DEFAULT_TOP_PADDING_DP = 2.0f;
	private static float DEFAULT_BOTTOM_PADDING_DP = 2.0f;
 
	public ArrowListView(Context context, AttributeSet attrs) {
		super(context, attrs);
 
		String strTopArrowPadding = attrs.getAttributeValue(null,
				"topArrowPadding");
		String strBottomArrowPadding = attrs.getAttributeValue(null,
				"bottomArrowPadding");
 
		topArrowPadding = convertDisplayUom(strTopArrowPadding,
				DEFAULT_TOP_PADDING_DP);
		bottomArrowPadding = convertDisplayUom(strBottomArrowPadding,
				DEFAULT_BOTTOM_PADDING_DP);
 
		Log.v("ArrowListView", String.valueOf(topArrowPadding));
	}
 
	/**
	 * 单位转换
	 */
	private float convertDisplayUom(String sour, float defaultValue) {
		try {
			if (sour.toLowerCase().endsWith("px")) {
				return Float.parseFloat(sour.toLowerCase().replace("px", ""));
			} else if (sour.toLowerCase().endsWith("dp")) {
				return Integer.parseInt(sour.toLowerCase().replace("dp",
						""))
						* scale + 0.5f;
			}
		} catch (Exception e) {
		}
 
		return (defaultValue * scale + 0.5f);
	}
 
	/**
	 * onDraw方法,根据ListView滚动位置绘出箭头.
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		Paint paint = new Paint();
 
		// 取得箭头的图片,此处是固定图片,其实上可以做成配置方式
		Bitmap topPic = ((BitmapDrawable) getResources().getDrawable(
				R.drawable.arrow_up)).getBitmap();
		Bitmap bottomPic = ((BitmapDrawable) getResources().getDrawable(
				R.drawable.arrow_down)).getBitmap();
 
		// 取得ListView的绘制区域大小
		Rect r = new Rect();
		this.getDrawingRect(r);
 
		// 计算箭头的绘制位置
		float top = r.top + topArrowPadding;
		float bottom = r.bottom - bottomArrowPadding - bottomPic.getHeight();
		float left = r.left + (r.right - r.left - topPic.getWidth()) / 2;
 
		// 计算是否需要绘制
		boolean drawTop = false;
		boolean drawBottom = false;
 
		if (this.getChildCount() > 0) {
			Rect rTop = new Rect();
			this.getChildAt(0).getLocalVisibleRect(rTop);
			Rect rBottom = new Rect();
			View lastChild = this.getChildAt(this.getChildCount() - 1);
			lastChild.getLocalVisibleRect(rBottom);
 
			drawTop = (this.getFirstVisiblePosition() > 0 || this
							.getFirstVisiblePosition() == 0
							&& rTop.top > 0);
			drawBottom = (this.getLastVisiblePosition() < this.getAdapter()
							.getCount() - 1 || this.getLastVisiblePosition() == this
							.getAdapter().getCount() - 1
							&& rBottom.bottom < lastChild.getHeight());
		}
		// 绘出箭头
		if (drawTop) {
			canvas.drawBitmap(topPic, left, top, paint);
		}
 
		if (drawBottom) {
			canvas.drawBitmap(bottomPic, left, bottom, paint);
		}
	}
}

就要点解释一下上面这段代码:
注意构造方法,我们必须继承public ArrowListView(Context context, AttributeSet attrs),这样才可以让这个类在xml定义文件中使用。
还要注意到,这里用了attrs.getAttributeValue来读取XML定义文件中的属性,其实有更好的方法,容我下次再讲解,这里先偷个懒。
convertDisplayUom方法是用来将dp转换成px的,可以看到由于我们用了getAttributeValue的方式,所以需要手动将String转成Float,很麻烦。
最后就是onDraw啦,计算出画箭头的位置,画出来就行了。
接下来就是布局文件的编写了

ArrowListView在XML文件中的使用:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent"
	android:orientation="vertical"
	>
	<TextView
		android:text="Arrow List View Sample"
		android:layout_width="fill_parent" android:layout_height="wrap_content"
	/>
	<net.learningandroid.lib.view.ArrowListView
		android:id="@+id/arrowListView"
		android:layout_width="fill_parent" android:layout_height="wrap_content"
		android:paddingTop="15dp" android:paddingBottom="20dp"
		android:layout_margin="10dp"
		android:background="@drawable/float_panel"
		android:layout_weight="1"
		android:cacheColorHint="#FFEDEDED" android:divider="#00EDEDED"
		topArrowPadding="5dp" bottomArrowPadding="10dp"
	/>
</LinearLayout>

这里需要注意的是自定义控件和其中的属性的写法,不再是ListView了,而是你自己编写的控件类的类名。其它的内容就是定义padding,background,以及取消了分隔线的显示。
用这个布局文件替代上一篇教程中的布局文件,但Adapter的定义不变,因为ArrowListView是继承自ListView的,所以原先的Adapter的使用是一样的。

最后我们来看下效果:

如何?只需要小心的调整ListView的Padding和ArrowPadding的值就可以控制箭头出现的位置,如果需要控制更多,比如更换图片,或者当顶部无内容时让箭头变暗、有内容时变亮,都可以用同样的方法。
并且,如果修改了Attribute的读取方法之后,还可以通过xml文件来指定箭头的图片。关于这部分,后面会再介绍,敬请关注。
  • 大小: 8.2 KB
  • 大小: 35.5 KB
分享到:
评论

相关推荐

    android UI进阶之实现listview中checkbox的多选与记录

    本篇文章将深入探讨如何在ListView中实现CheckBox的多选功能,并记录用户的选定状态。ListView是Android中常用的一个控件,它允许我们以列表的形式展示大量数据,而CheckBox则提供了一种让用户进行多选操作的方式。 ...

    android UI进阶之实现listview的分页加载

    本篇文章将深入探讨如何在Android中实现ListView的分页加载,提升用户体验并优化资源使用。 首先,理解分页加载的基本概念。分页加载是指在用户滚动到列表底部时,动态地从服务器或本地数据库加载更多数据,而不是...

    viewpage嵌套listview,效果:滑动listview删除,滑动非listview区域viewpage翻页

    在Android开发中,有时我们需要实现复杂布局以满足用户交互需求,比如在一个页面中同时展示一个横向滚动的ViewPager和一个纵向滚动的ListView。标题"viewpage嵌套listview,效果:滑动listview删除,滑动非listview...

    android_UI进阶之实现listview的下拉加载

    在上述代码中,我们定义了一个RelativeLayout作为ListView的头部视图,并在其中放置了一个ProgressBar用于显示加载状态,一个ImageView用来显示下拉箭头,以及两个TextView分别用于显示加载进度和最后更新时间。...

    解决scrollView和listview滚动冲突,实现listview滑动到顶端和底部之后还能拖拽一定的距离,松开后返回

    在Android开发中,ScrollView和ListView是两种常用的布局组件,它们分别用于实现可滚动的大视图和展示多行可滚动的数据列表。然而,在实际应用中,当这两种组件同时存在于一个界面时,滚动冲突的问题就会出现,导致...

    带箭头排序的ListView示例

    "带箭头排序的ListView示例"是一个具体的开发实践,它展示了如何在ListView中实现数据的动态排序,并通过箭头图标来指示排序状态。这个示例的核心是通过自定义适配器和点击事件处理来实现功能。 首先,我们需要理解...

    Android:弹性ListView

    这种效果在用户滚动到列表顶部或底部时,会有一个自然的反弹动作,增加了用户体验的流畅性和吸引力。在本篇文章中,我们将深入探讨如何在Android应用中实现弹性ListView,以及它的工作原理和相关知识点。 1. **基础...

    androidUI进阶之实现listview的下拉加载.pdf

    另外,在实现 ListView 的下拉加载功能时,需要注意以下几点: * 监听触摸和滑动操作,计算头部 View 的显示状态。 * 在 ListView 头部加载一个视图,包括 ProgressBar、ImageView 和 TextView 等控件。 * 实现 ...

    基于ListView实现头部、底部视差效果

    在本教程中,我们将探讨如何在ListView中实现头部和底部的视差效果。 首先,我们需要创建一个自定义的ListView,这可以通过继承AbsListView或者直接使用ListView并重写其滚动方法来实现。关键在于监听ListView的...

    PopupWindow+ListView+在item顶部与底部跳跃

    PopupWindow和ListView是Android开发中常用的两种组件,它们在实现丰富的用户交互时起着关键作用。本篇文章将深入探讨如何将PopupWindow与ListView结合使用,让ListView的item在顶部与底部之间实现动态跳跃效果。 ...

    Node.js-AndroidListview返回顶部快速返回顶部的功能实现详解代码

    本篇文章将详细讲解如何在ListView中实现“返回顶部”功能,即快速回到ListView的第一项。这一功能对于用户在浏览长列表时非常方便,常见于聊天应用、新闻列表等场景。 1. **基础概念** - ListView:Android中的一...

    Android:ListView实现QQ列表

    在这个"Android:ListView实现QQ列表"的实践中,我们将深入理解如何利用ListView和Adapter来创建一个类似于QQ消息列表的界面。 首先,我们来探讨ListView的基础。ListView是一个视图容器,可以展示多行数据,并且只...

    Android 实现ListView滚动到底部自动加载数据

    总之,实现Android ListView滚动到底部自动加载数据涉及到的主要步骤包括:设置适配器、监听滚动事件、判断是否滚动到底部、加载新数据和更新列表。这个过程需要对Android的基础组件和数据操作有深入的理解,同时也...

    Android编程实现ListView中item部分区域添加点击事件功能

    需求如题目:Android listview中item部分区域添加点击事件,在一个界面显示了listview,但显示的内容分为上下两部分,分别是白色的背景和蓝色的背景,现在需要只点击蓝色的背景,才能跳转到其他界面,解决方式如下:...

    自定义ListView实现下拉刷新+加载更多功能Demo

    在Android开发中,自定义ListView实现下拉刷新和加载更多的功能是常见的需求,尤其是在构建具有数据流滚动和实时更新的应用程序时。这个"自定义ListView实现下拉刷新+加载更多功能Demo"旨在帮助开发者理解如何集成...

    android listView顶部悬浮效果实现

    本篇文章将详细介绍如何在Android中实现ListView的顶部悬浮功能。 首先,我们理解一下“顶部悬浮”效果的原理。当ListView滚动时,如果某个列表项(如标题)到达顶部,它应该被固定在屏幕顶部,即使ListView继续...

    listview内容超出屏幕高度,自动显示回到listview顶部的按钮

    在Android开发中,ListView是一种常用的控件,用于展示大量数据并允许用户滚动浏览。当ListView的内容高度超过屏幕显示范围时,用户可能需要滚动才能查看所有内容。为了方便用户快速回到列表顶部,通常会添加一个...

    在ListView中嵌套Switch开关,点击ListView条目来切换Switch的状态

    将Switch嵌套在ListView中,可以实现用户通过点击列表条目来切换Switch的状态,从而提供更丰富的交互体验。以下是关于这个主题的详细知识点: 1. **ListView的使用**: - ListView是Android中的一个视图容器,主要...

    Android 自定义ListView实现底部分页刷新与顶部下拉刷新

    Android 自定义ListView实现底部分页刷新与顶部下拉刷新 一.ListView 底部分页加载 整个底部分页加载,主要分一下几步: 1.加载底部自定义View; 2.响应OnScrollListener监听事件,onScroll方法记录最后可见的View ...

    listview分页加载(底部loading)

    在ListView中,底部加载通常通过添加一个Footer视图来实现。当用户滚动到列表底部时,这个Footer视图会显示一个加载指示器(如旋转的菊花图标),表示正在后台加载新数据。一旦数据加载完成,新条目将被添加到...

Global site tag (gtag.js) - Google Analytics