经常看到一些Contact类的软件软件联系人列表在滚动时会在屏幕中间弹出一个提示信息,就是当前位置的联系人序号之类的,尝试实现了一下
先看效果:
中间弹出的就是一个类似于Overlay的层
布局文件 pop_overlay.xml
- <?xml version="1.0" encoding="utf-8"?>
- <TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:textSize="70sp"
- android:textColor="#99ff00ff"
- android:background="#99fff34f"
- android:minWidth="80dip"
- android:maxWidth="80dip"
- android:padding="10dip"
- android:gravity="center"
- />
在onCreate方法中加载这个View并且通过addView加入到Activity中
- //滚动时弹出的提示框
- txtOverlay = (TextView) LayoutInflater.from(this).inflate(R.layout.pop_overlay, null);
- // 默认设置为不可见。
- txtOverlay.setVisibility(View.INVISIBLE);
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
- PixelFormat.TRANSLUCENT);
- windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- windowManager.addView(txtOverlay, lp);
然后可以通过实现 ListView.OnScrollListener接口来重写 onScroll 和 onScrollStateChanged方法
- boolean visible;
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- Log.i("bb", "onScroll");
- Log.i("bb", "visible:"+visible);
- int index = cursor.getColumnIndex("display_name");
- if (visible) {
- cursor.moveToPosition(firstVisibleItem);
- String firstChar = Pinyin4j.getFirstChar(cursor.getString(index));
- txtOverlay.setText(firstChar);
- txtOverlay.setVisibility(View.VISIBLE);
- }
- }
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- visible = true;
- Log.i("bb", "onScrollStateChanged");
- //在onScrollStateChanged (AbsListView view, int scrollState) 中,scrollState有三种状态,
- //分别是开始滚动(SCROLL_STATE_FLING ),正在滚动(SCROLL_STATE_TOUCH_SCROLL ), 已经停止(SCROLL_STATE_IDLE ),
- if (scrollState == ListView.OnScrollListener.SCROLL_STATE_IDLE) {
- txtOverlay.setVisibility(View.INVISIBLE);
- visible = false;
- }
- }
这两个方法的调用时机是不同的,可以自己打印看一下
这里显示的是用户中文名的首字母 通过 pingyin4j.jar 来实现的 可以下载来试下 还可以设置一些参数的
下面是调试代码:
- import java.util.HashSet;
- import java.util.Set;
- import net.sourceforge.pinyin4j.PinyinHelper;
- import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
- import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
- import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
- import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
- import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
- public class Pinyin4j {
- /**
- * 字符串集合转换字符串(逗号分隔)
- */
- public static String makeStringByStringSet(Set<String> stringSet) {
- StringBuilder str = new StringBuilder();
- int i = 0;
- for (String s : stringSet) {
- if (i == stringSet.size() - 1) {
- str.append(s);
- } else {
- str.append(s + ",");
- }
- i++;
- }
- return str.toString().toLowerCase();
- }
- /**
- * 获取拼音集合
- */
- public static Set<String> getPinyin(String src) {
- if (src != null && !src.trim().equalsIgnoreCase("")) {
- char[] srcChar;
- srcChar = src.toCharArray();
- // 汉语拼音格式输出类
- HanyuPinyinOutputFormat hanYuPinOutputFormat = new HanyuPinyinOutputFormat();
- // 输出设置,大小写,音标方式等
- hanYuPinOutputFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
- hanYuPinOutputFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
- hanYuPinOutputFormat.setVCharType(HanyuPinyinVCharType.WITH_V);
- String[][] temp = new String[src.length()][];
- for (int i = 0; i < srcChar.length; i++) {
- char c = srcChar[i];
- // 是中文或者a-z或者A-Z转换拼音(我的需求,是保留中文或者a-z或者A-Z)
- if (String.valueOf(c).matches("[//u4E00-//u9FA5]+")) {
- try {
- temp[i] = PinyinHelper.toHanyuPinyinStringArray(
- srcChar[i], hanYuPinOutputFormat);
- } catch (BadHanyuPinyinOutputFormatCombination e) {
- e.printStackTrace();
- }
- } else if (((int) c >= 65 && (int) c <= 90)
- || ((int) c >= 97 && (int) c <= 122)) {
- temp[i] = new String[] { String.valueOf(srcChar[i]) };
- } else {
- temp[i] = new String[] { "" };
- }
- }
- String[] pingyinArray = Exchange(temp);
- Set<String> pinyinSet = new HashSet<String>();
- for (int i = 0; i < pingyinArray.length; i++) {
- pinyinSet.add(pingyinArray[i]);
- }
- return pinyinSet;
- }
- return null;
- }
- /**
- * 递归
- */
- public static String[] Exchange(String[][] strJaggedArray) {
- String[][] temp = DoExchange(strJaggedArray);
- return temp[0];
- }
- /**
- * 递归
- */
- private static String[][] DoExchange(String[][] strJaggedArray) {
- int len = strJaggedArray.length;
- if (len >= 2) {
- int len1 = strJaggedArray[0].length;
- int len2 = strJaggedArray[1].length;
- int newlen = len1 * len2;
- String[] temp = new String[newlen];
- int Index = 0;
- for (int i = 0; i < len1; i++) {
- for (int j = 0; j < len2; j++) {
- temp[Index] = strJaggedArray[0][i] + strJaggedArray[1][j];
- Index++;
- }
- }
- String[][] newArray = new String[len - 1][];
- for (int i = 2; i < len; i++) {
- newArray[i - 1] = strJaggedArray[i];
- }
- newArray[0] = temp;
- return DoExchange(newArray);
- } else {
- return strJaggedArray;
- }
- }
- public static String getFirstChar(String str) {
- return makeStringByStringSet(getPinyin(str)).substring(0, 1);
- }
- /**
- * @param args
- */
- public static void main(String[] args) {
- String str = "测试";
- System.out.println(makeStringByStringSet(getPinyin(str)));
- }
- }
下面看弹出菜单的创建
- //监听条目单击事件
- listView.setOnItemClickListener(new OnItemClickListener(){
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id) {
- TextView tv = (TextView)view.findViewById(R.id.phonename);
- Toast.makeText(ListViewDemo.this, tv.getText(), Toast.LENGTH_LONG).show();
- }
- });
- listView.setOnItemLongClickListener(new OnItemLongClickListener(){
- @Override
- public boolean onItemLongClick(AdapterView<?> parent, View view,
- int position, long id) {
- Toast.makeText(ListViewDemo.this, "长按一次", Toast.LENGTH_LONG).show();
- return false;//如果返回true 就不会调用下面onCreateContextMenu事件
- }
- });
- //长按弹出菜单选项的点击选择事件监听
- final OnMenuItemClickListener mOnMenuItemClickListener = new OnMenuItemClickListener(){
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- switch (item.getItemId()) {
- case 0:
- Toast.makeText(ListViewDemo.this, "test1", Toast.LENGTH_LONG).show();
- break;
- case 1:
- Toast.makeText(ListViewDemo.this, "test2", Toast.LENGTH_LONG).show();
- break;
- case 2:
- Toast.makeText(ListViewDemo.this, "test3", Toast.LENGTH_LONG).show();
- break;
- case 3:
- Toast.makeText(ListViewDemo.this, "test4", Toast.LENGTH_LONG).show();
- break;
- }
- return false;
- }
- };
- //监听长按事件 长按时弹出选择菜单
- listView.setOnCreateContextMenuListener(new OnCreateContextMenuListener(){
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view,ContextMenuInfo arg2) {
- menu.setHeaderTitle("提示框");
- menu.add(0, 0, 0, "test1").setOnMenuItemClickListener(mOnMenuItemClickListener);
- menu.add(0, 1, 1, "test2").setOnMenuItemClickListener(mOnMenuItemClickListener);
- menu.add(0, 2, 2, "test3").setOnMenuItemClickListener(mOnMenuItemClickListener);
- menu.add(0, 3, 3, "test4").setOnMenuItemClickListener(mOnMenuItemClickListener);
- }
- });
效果如上图,这里就有ListView种的几个点击事件
首先是单击事件 通过setOnItemClickListener 来监听
长按事件 通过 setOnItemLongClickListener 来监听 如果是长按就可以通过setOnCreateContextMenuListener这个事件来创建弹出菜单,注意如果要通过这种方式创建菜单需要在onItemLongClick方法中返回false
通过setOnCreateContextMenuListener事件来监听弹出菜单的点击事件
总之这里有N多的事件
还有一点看一下ListView的每个条目Item实现点击切换底色的效果
如图
点击是底色变成如果的颜色
这个可以在Item的布局文件中实现 来看布局文件 listviewdemoitem.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#ffffff"
- >
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:background="@drawable/listview_selected"
- android:padding="6px"
- >
- <TextView
- android:id="@+id/phonename"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="20px"
- android:textColor="#000000"
- />
- <TextView
- android:layout_below="@id/phonename"
- android:id="@+id/phonenumber"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="16px"
- android:textColor="#000000"
- />
- <ImageView
- android:layout_alignParentRight="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/menu_city_manager"
- android:layout_gravity="right"
- />
- </RelativeLayout>
- </LinearLayout>
外面是一个LinerLayout 作为底色 防止滚动的时候底色变成黑色
里面用一个RelativeLayout实现了布局调整,它的android:background="@drawable/listview_selected" 属性通过一个Selector
来实现焦点 点击等操作时的背景切换
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@drawable/list_selector_background_pressed" />
- </selector>
这里简单实现了一下,还可以有其他的设置 譬如 android:state_focus等