Android:第三方开源PinnedSectionListView(分组标签悬停滑入滑出)实现联系人通讯录

常用的联系人、通讯录,会按照联系人的姓氏从A,B,C,,,X,Y,Z,这样归类排列下去,方便用户快速查找和定位。PinnedSectionListView是一个第三方的开源框架,在github上的链接地址是: https://github.com/beworker/pinned-section-listview  。Android PinnedSectionListView不仅是一个实现上述功能且有“pinded”的ListView,而且PinnedSectionListView在向上滚动或者向下滚动时候会有一些特殊效果:分组的标签会悬停在ListView的顶部,直到该分组被滑出/滑入整个ListView的可视界面而呈现出弹入弹出效果。

实现上述功能,直接将PinnedSectionListView作为一个普通的ListView即可,但重点是在构造PinnedSectionListView适配器Adapter时,每一个Item需要小心设置View Type。

实现分组标签悬停滑入滑出效果,只需将PinnedSectionListView.java倒入自己的项目即可:



PinnedSectionListView.java代码如下:

/*
 * Copyright (C) 2013 Sergej Shafarenka, halfbit.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file kt in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hb.views;

import zhangphil.contacts.BuildConfig;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AbsListView;
import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SectionIndexer;

/**
 * ListView, which is capable to pin section views at its top while the rest is
 * still scrolled.
 */
public class PinnedSectionListView extends ListView {

	// -- inner classes

	/**
	 * List adapter to be implemented for being used with PinnedSectionListView
	 * adapter.
	 */
	public static interface PinnedSectionListAdapter extends ListAdapter {
		/**
		 * This method shall return 'true' if views of given type has to be
		 * pinned.
		 */
		boolean isItemViewTypePinned(int viewType);
	}

	/** Wrapper class for pinned section view and its position in the list. */
	static class PinnedSection {
		public View view;
		public int position;
		public long id;
	}

	// -- class fields

	// fields used for handling touch events
	private final Rect mTouchRect = new Rect();
	private final PointF mTouchPoint = new PointF();
	private int mTouchSlop;
	private View mTouchTarget;
	private MotionEvent mDownEvent;

	// fields used for drawing shadow under a pinned section
	private GradientDrawable mShadowDrawable;
	private int mSectionsDistanceY;
	private int mShadowHeight;

	/** Delegating listener, can be null. */
	OnScrollListener mDelegateOnScrollListener;

	/** Shadow for being recycled, can be null. */
	PinnedSection mRecycleSection;

	/** shadow instance with a pinned view, can be null. */
	PinnedSection mPinnedSection;

	/**
	 * Pinned view Y-translation. We use it to stick pinned view to the next
	 * section.
	 */
	int mTranslateY;

	/** Scroll listener which does the magic */
	private final OnScrollListener mOnScrollListener = new OnScrollListener() {

		@Override
		public void onScrollStateChanged(AbsListView view, int scrollState) {
			if (mDelegateOnScrollListener != null) { // delegate
				mDelegateOnScrollListener.onScrollStateChanged(view,
						scrollState);
			}
		}

		@Override
		public void onScroll(AbsListView view, int firstVisibleItem,
				int visibleItemCount, int totalItemCount) {

			if (mDelegateOnScrollListener != null) { // delegate
				mDelegateOnScrollListener.onScroll(view, firstVisibleItem,
						visibleItemCount, totalItemCount);
			}

			// get expected adapter or fail fast
			ListAdapter adapter = getAdapter();
			if (adapter == null || visibleItemCount == 0)
				return; // nothing to do

			final boolean isFirstVisibleItemSection = isItemViewTypePinned(
					adapter, adapter.getItemViewType(firstVisibleItem));

			if (isFirstVisibleItemSection) {
				View sectionView = getChildAt(0);
				if (sectionView.getTop() == getPaddingTop()) { // view stic
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值