在有些Android應用中,為了方便快速定位,經常會看到屏幕右側有一個字母索引表,今天嘗試使用自定義View的方式實現了索引表的基本布局。
字母索引表的樣式如下面的示意圖所示,
此時我們至少需要知道以下幾個參數值:1.字母大小;2.單個字母所在區域的寬度;3.單個字母所在區域的高度。現在看如何實現:
/**
* 26個英文字母以及一個#字符,#字符是為了索引非英文字母的內容,比如電話號碼。
*/
private String[] mAlphabetTable = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "#" }; /** * 單個字母的大小 */ private int mAlphabetSize = 0; /** * 字母表的寬度 */ private int mWidth = 0; /** * 字母表的高度 */ private int mHeight = 0; /** * 窗口高度 */ private int mDisplayHeight; /** * 單個字母所在區域的高度 */ private int mStepPixel; private int mFastScrollViewHeight = 0; private Rect[] mAlphabetRect = new Rect[27]; private Rect mPointRectAll = new Rect(); private static int mAlphabetLeftPadding = 0; private boolean[] mPoint = new boolean[27]; public AlphabetFastScorll(Context context) { this(context, null); } public AlphabetFastScorll(Context context, AttributeSet attrs) { super(context, attrs); this.setAlpha(1.0f);//設置透明度1 DisplayMetrics metric = new DisplayMetrics(); ((WindowManager) getContext().getSystemService(getContext().WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metric); mDisplayHeight = metric.heightPixels;//獲取窗口高度 }
在構造函數里,只設置了索引表的透明度和初始化mDisplayHeight參數。索引表的繪制工作大部分是在onDraw()里完成。
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mStepPixel = getContext().getResources().getDimensionPixelOffset(R.dimen.fast_scroll_size); mFastScrollViewHeight = mStepPixel * 27;
//初始化27個字母每個字母對應所在區域的大小范圍 InitAlphabetRect();
//初始化字母索引表的背景大小 initPointRect(mFastScrollViewHeight, mStepPixel); //設置背景顏色 Paint paintB = new Paint(); paintB.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent)); //paintB.setAlpha(0); canvas.drawRect(mPointRectAll, paintB);
//設置字母中大小,顏色,位置等 Paint paint = new Paint(); float textSize = getContext().getResources().getDimensionPixelOffset(R.dimen.asus_index_size); paint.setColor(ContextCompat.getColor(getContext(), R.color.fast_scroll_text_color)); paint.setTextAlign(Align.CENTER); paint.setTextSize(textSize); paint.setAntiAlias(true); for (int i = 0; i < mAlphabetRect.length; i++) { int x = (mAlphabetRect[i].left + mAlphabetRect[i].right) / 2; int y = mAlphabetRect[i].bottom; y = y - (int) (0.5 * (mStepPixel - textSize));
//字母繪制在mAlphabetRect[i]區域中間 canvas.drawText(mAlphabetTable[i], x, y, paint); } } private void InitAlphabetRect() { for (int i = 0; i < mAlphabetRect.length; i++) { mAlphabetRect[i] = new Rect(); mAlphabetRect[i].left = mAlphabetLeftPadding; mAlphabetRect[i].right = mAlphabetLeftPadding + this.getWidth(); //Log.d(TAG,"InitAlphabetRect right = " + mAlphabetRect[i].right); if (i == 0) { mAlphabetRect[i].top = 0; mAlphabetRect[i].bottom = mStepPixel; } else { mAlphabetRect[i].top = mAlphabetRect[i-1].top + mStepPixel; mAlphabetRect[i].bottom = mAlphabetRect[i].top + mStepPixel; } } } private void initPointRect(int fastScrollViewHeight, int stepPixel) { int canvasWidth = getContext().getResources().getDimensionPixelOffset(R.dimen.asus_index_canvas_width); mPointRectAll = new Rect(); mPointRectAll.left = 0; mPointRectAll.right = canvasWidth; mPointRectAll.top = 0; mPointRectAll.bottom = this.getHeight(); }
在onDraw()里做了以下幾件事情:
1,初始化索引表字母所在區域的范圍:新建一個Rect對象,設置其左右和上下大小。寬度大小由布局文件中提供,高度為mStepPixel。
2,初始化索引表背景范圍:寬 = asus_index_canvas_width,高 = this.getHeight();
3,已經知道每個字母所在區域范圍以及索引背景范圍,新建兩個Paint在Canves上進行繪制;
通過以上幾步就可以簡單實現索引表控件,光光顯示一個索引表肯定沒啥意義。一般都是將索引表與ListView組合,實現快速定位功能。下篇准備模仿聯系人應用,實現通過索引表快速定位到聯系人。