IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android系统联系人全特效实现(上),分组导航和挤压动画,吐血整理 -> 正文阅读

[移动开发]Android系统联系人全特效实现(上),分组导航和挤压动画,吐血整理

下面我们就来开始实现,新建一个 Android 项目,命名为 ContactsDemo。首先我们还是先来完成布局文件,打开或新建 activity_main.xml 作为程序的主布局文件,在里面加入如下代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <ListView
        android:id="@+id/contacts_list_view"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:fadingEdge="none" >
    </ListView>
    
     <LinearLayout
        android:id="@+id/title_layout"
        android:layout_width="fill_parent"
        android:layout_height="18dip"
        android:layout_alignParentTop="true"
        android:background="#303030" >
 
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginLeft="10dip"
            android:textColor="#ffffff"
            android:textSize="13sp" />
    </LinearLayout>
 
</RelativeLayout> 

布局文件很简单,里面放入了一个 ListView,用于展示联系人信息。另外还在头部放了一个 LinearLayout,里面包含了一个 TextView,它的作用是在界面头部始终显示一个当前分组。

然后新建一个 contact_item.xml 的布局,这个布局用于在 ListView 中的每一行进行填充,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <LinearLayout
        android:id="@+id/sort_key_layout"
        android:layout_width="fill_parent"
        android:layout_height="18dip"
        android:background="#303030" >
 
        <TextView
            android:id="@+id/sort_key"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginLeft="10dip"
            android:textColor="#ffffff"
            android:textSize="13sp" />
    </LinearLayout>
 
    <LinearLayout
        android:id="@+id/name_layout"
        android:layout_width="fill_parent"
        android:layout_height="50dip" >
 
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="10dip"
            android:layout_marginRight="10dip"
            android:src="@drawable/icon" />
 
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:textColor="#ffffff"
            android:textSize="22sp" />
    </LinearLayout>
 
</LinearLayout> 

在这个布局文件中,首先是放入了一个和前面完成一样的分组布局,因为不仅界面头部需要展示分组,在每个分组内的第一个无素之前都需要展示分组布局。然后是加入一个简单的 LinearLayout,里面包含了一个 ImageView 用于显示联系人头像,还包含一个 TextView 用于显示联系人姓名。

这样我们的布局文件就全部写完了,下面开始来真正地实现功能。

先从简单的开始,新建一个 Contact 实体类:

public class Contact {
 
	/**
	 * 联系人姓名
	 */
	private String name;
 
	/**
	 * 排序字母
	 */
	private String sortKey;
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public String getSortKey() {
		return sortKey;
	}
 
	public void setSortKey(String sortKey) {
		this.sortKey = sortKey;
	}
 
} 

这个实体类很简单,只包含了联系人姓名和排序键。

接下来完成联系人列表适配器的编写,新建一个 ContactAdapter 类继承自 ArrayAdapter,加入如下代码:

public class ContactAdapter extends ArrayAdapter<Contact> {
 
	/**
	 * 需要渲染的item布局文件
	 */
	private int resource;
 
	/**
	 * 字母表分组工具
	 */
	private SectionIndexer mIndexer;
 
	public ContactAdapter(Context context, int textViewResourceId, List<Contact> objects) {
		super(context, textViewResourceId, objects);
		resource = textViewResourceId;
	}
 
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		Contact contact = getItem(position);
		LinearLayout layout = null;
		if (convertView == null) {
			layout = (LinearLayout) LayoutInflater.from(getContext()).inflate(resource, null);
		} else {
			layout = (LinearLayout) convertView;
		}
		TextView name = (TextView) layout.findViewById(R.id.name);
		LinearLayout sortKeyLayout = (LinearLayout) layout.findViewById(R.id.sort_key_layout);
		TextView sortKey = (TextView) layout.findViewById(R.id.sort_key);
		name.setText(contact.getName());
		int section = mIndexer.getSectionForPosition(position);
		if (position == mIndexer.getPositionForSection(section)) {
			sortKey.setText(contact.getSortKey());
			sortKeyLayout.setVisibility(View.VISIBLE);
		} else {
			sortKeyLayout.setVisibility(View.GONE);
		}
		return layout;
	}
 
	/**
	 * 给当前适配器传入一个分组工具。
	 * 
	 * @param indexer
	 */
	public void setIndexer(SectionIndexer indexer) {
		mIndexer = indexer;
	}
 
} 

上面的代码中,最重要的就是 getView 方法,在这个方法中,我们使用 SectionIndexer 的 getSectionForPosition 方法,通过当前的 position 值拿到了对应的 section 值,然后再反向通过刚刚拿到的 section 值,调用 getPositionForSection 方法,取回新的 position 值。如果当前的 position 值和新的 position 值是相等的,那么我们就可以认为当前 position 的项是某个分组下的第一个元素,我们应该将分组布局显示出来,而其它的情况就应该将分组布局隐藏。

最后我们来编写程序的主界面,打开或新建 MainActivity 作为程序的主界面,代码如下所示:

public class MainActivity extends Activity {
 
	/**
	 * 分组的布局
	 */
	private LinearLayout titleLayout;
 
	/**
	 * 分组上显示的字母
	 */
	private TextView title;
 
	/**
	 * 联系人ListView
	 */
	private ListView contactsListView;
 
	/**
	 * 联系人列表适配器
	 */
	private ContactAdapter adapter;
 
	/**
	 * 用于进行字母表分组
	 */
	private AlphabetIndexer indexer;
 
	/**
	 * 存储所有手机中的联系人
	 */
	private List<Contact> contacts = new ArrayList<Contact>();
 
	/**
	 * 定义字母表的排序规则
	 */
	private String alphabet = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
	/**
	 * 上次第一个可见元素,用于滚动时记录标识。
	 */
	private int lastFirstVisibleItem = -1;
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		adapter = new ContactAdapter(this, R.layout.contact_item, contacts);
		titleLayout = (LinearLayout) findViewById(R.id.title_layout);
		title = (TextView) findViewById(R.id.title);
		contactsListView = (ListView) findViewById(R.id.contacts_list_view);
		Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
		Cursor cursor = getContentResolver().query(uri,
				new String[] { "display_name", "sort_key" }, null, null, "sort_key");
		if (cursor.moveToFirst()) {
			do {
				String name = cursor.getString(0);
				String sortKey = getSortKey(cursor.getString(1));
				Contact contact = new Contact();
				contact.setName(name);
				contact.setSortKey(sortKey);
				contacts.add(contact);
			} while (cursor.moveToNext());
		}
		startManagingCursor(cursor);
		indexer = new AlphabetIndexer(cursor, 1, alphabet);
		adapter.setIndexer(indexer);
		if (contacts.size() > 0) {
			setupContactsListView();
		}
	}
 
	/**
	 * 为联系人ListView设置监听事件,根据当前的滑动状态来改变分组的显示位置,从而实现挤压动画的效果。
	 */
	private void setupContactsListView() {
		contactsListView.setAdapter(adapter);
		contactsListView.setOnScrollListener(new OnScrollListener() {
			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
			}
 
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
					int totalItemCount) {
				int section = indexer.getSectionForPosition(firstVisibleItem);
				int nextSecPosition = indexer.getPositionForSection(section + 1);
 
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:39:38  更:2021-09-04 17:41:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:55:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码