微信的通讯录首字母滑动的实现
国际规矩,关门,放截图
左边是我写的,右边是微信的,功能差不多了
先讲使用到的东西
列表使用的是ExpandableListView,上面的字母就是Group来的
SideBar 的实现是使用了一个View,ABCD的排布是第一次初始化的时候使用Cavans画上去的
小方块就是一个在列表上面的TextView
具体情况,请看代码
Side.java
package auggie.demo.sidebardemo.widget; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import auggie.demo.sidebardemo.R; /** * Created With Android Studio * User Auggie Liang * Date 13-9-3 * Time 上午9:33 * 仿微信通许录旁边的bar */ public class SideBar extends View { public static final String TAG = SideBar.class.getName(); private String[] letters; private OnLetterTouchListener letterTouchListener; public SideBar(Context context) { super(context); init(context); } public SideBar(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public SideBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } public void init(Context context){ } /** * 每一项的高度 */ private float itemHeight = -1; private Paint paint; private Bitmap letterBitmap; @Override protected void onDraw(Canvas canvas) { if(letters == null){ return ; } if(itemHeight == -1){ itemHeight = getHeight() /letters.length; } if(paint == null){ //初始化画笔 paint = new Paint(); paint.setTextSize(itemHeight - 4); //字体颜色 paint.setColor(getResources().getColor(R.color.white)); paint.setFlags(Paint.ANTI_ALIAS_FLAG); //创建一张包含所有列表的图 Canvas mCanvas = new Canvas(); letterBitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); // Log.v(TAG, "width,height" + getMeasuredWidth() + ":" + getMeasuredHeight()); mCanvas.setBitmap(letterBitmap); float widthCenter = getMeasuredWidth() / 2.0F; //画字符上图片中 for(int i = 0 ; i < letters.length; i ++){ mCanvas.drawText(letters[i], widthCenter-paint.measureText(letters[i])/2, itemHeight * i +itemHeight,paint); } } if(letterBitmap != null){//图片不为空就画图 canvas.drawBitmap(letterBitmap,0,0,paint); } super.onDraw(canvas); } @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); if(letterTouchListener == null || letters == null){ return false; } switch (event.getAction()){ case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: Log.v(TAG, "action down or move"); int position = (int) (event.getY() / itemHeight + 1); if(position >= 0 && position < letters.length){ letterTouchListener.onLetterTouch(letters[position],position); } return true; case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_UP: Log.v(TAG, "action up"); letterTouchListener.onActionUp(); return true; } return false; } /** * 设置显示在边栏上的字母 * @param letters */ public void setShowString(String[] letters){ this.letters = letters; } /** * 设置点击某个字母的时候 * @param listener */ public void setOnLetterTouchListener (OnLetterTouchListener listener){ this.letterTouchListener = listener; } public interface OnLetterTouchListener{ /** * 某个字母被按下的时候 * @param letter * @param position */ public void onLetterTouch(String letter, int position); /** * 触控手指离开的时候 */ public void onActionUp(); } }
MainActivity.java
package auggie.demo.sidebardemo; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; import auggie.demo.sidebardemo.widget.SideBar; public class MainActivity extends Activity { ExpandableListView expandableListView; TextView tViewShowLetter; private static String[] letters; private HashMap<String, ArrayList<String>> lettersDivider = new HashMap<String, ArrayList<String>>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //test data; letters = getResources().getStringArray(R.array.alphabet); //由于是演示就不是用真实数据了 ArrayList<String> names = new ArrayList<String>(); names.add("heheh"); names.add("我了个"); names.add("并不是我"); names.add("呵呵"); names.add("嘻嘻"); names.add("啦啦"); names.add("lel"); names.add("lle"); names.add("lele"); names.add("hehe"); for (String letter : letters) { lettersDivider.put(letter, names); } tViewShowLetter = (TextView) findViewById(R.id.tView_letter); expandableListView = (ExpandableListView) findViewById(R.id.expandableListView); expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { return true;//屏蔽点击收缩事件 } }); expandableListView.setAdapter(new MyBaseAdapter()); SideBar sideBar = ((SideBar) findViewById(R.id.side_bar)); sideBar.setOnLetterTouchListener(new SideBar.OnLetterTouchListener() { @Override public void onLetterTouch(String letter, int position) { tViewShowLetter.setVisibility(View.VISIBLE); tViewShowLetter.setText(letter); expandableListView.setSelectedGroup(position); } @Override public void onActionUp() { tViewShowLetter.setVisibility(View.GONE); } }); sideBar.setShowString(letters); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } class MyBaseAdapter extends BaseExpandableListAdapter { @Override public int getGroupCount() { return letters.length; } @Override public int getChildrenCount(int groupPosition) { return lettersDivider.get(letters[groupPosition]).size(); } @Override public Object getGroup(int groupPosition) { return null; } @Override public Object getChild(int groupPosition, int childPosition) { return null; } @Override public long getGroupId(int groupPosition) { return 0; } @Override public long getChildId(int groupPosition, int childPosition) { return 0; } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { if (!isExpanded) { expandableListView.expandGroup(groupPosition);//展开组 } if (convertView == null) { convertView = View.inflate(MainActivity.this, R.layout.adapter_group_view, null); convertView.setTag(new GroupViewHolder(convertView)); } GroupViewHolder holder = (GroupViewHolder) convertView.getTag(); holder.tViewGroupName.setText(letters[groupPosition]); return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { if (convertView == null) { convertView = View.inflate(MainActivity.this, R.layout.adapter_child_view, null); convertView.setTag(new ChildViewHolder(convertView)); } ChildViewHolder holder = (ChildViewHolder) convertView.getTag(); holder.tViewChildName.setText(lettersDivider.get(letters[groupPosition]).get(childPosition)); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } class GroupViewHolder { TextView tViewGroupName; public GroupViewHolder(View parent) { tViewGroupName = (TextView) parent.findViewById(R.id.tView_group_name); } } class ChildViewHolder { TextView tViewChildName; public ChildViewHolder(View parent) { tViewChildName = (TextView) parent.findViewById(R.id.tView_child_name); } } } }
主布局acivity_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:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <ExpandableListView android:layout_height="match_parent" android:layout_width="match_parent" android:groupIndicator="@null" android:id="@+id/expandableListView"/> <auggie.demo.sidebardemo.widget.SideBar android:id="@+id/side_bar" android:layout_alignParentRight="true" android:background="@color/black" android:layout_width="14dp" android:layout_height="match_parent"/> <TextView android:id="@+id/tView_letter" android:layout_width="60dp" android:layout_height="60dp" android:textSize="35sp" android:visibility="gone" android:gravity="center" tools:text="A" android:textColor="@color/white" android:background="@color/blue" android:layout_centerInParent="true"/> </RelativeLayout>