Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android ListView A-Z側邊欄字母排序,點擊處扭曲成半圓

Android ListView A-Z側邊欄字母排序,點擊處扭曲成半圓

編輯:關於Android編程

 

\

最近在做通訊錄看到360通訊錄和索尼系統內置通訊錄有這個效果,就是點擊聯系人列表的A-Z側邊欄時,A-Z欄的被觸摸處會扭曲成半圓,半圓可以隨著手指在A-Z移動。索尼手機的比較高級,扭曲和恢復的過程有阻尼效果,360的沒有任何效果就一伸一縮。所本人實現了個360效果一摸一樣的,A-Z側邊欄。

 

 

一.實現原理講解:

我們知道正常的A-Z欄每個字母的坐標的Y值應該是一樣的(起碼差不多一樣),所以繪制出來的時候三豎直的。因此我只要按照如下步驟,就可以實現圖中的效果:

1.當A-Z欄被觸摸時,通過setLayoutParams()方法改變他的寬度(本列為100dp)使得它有足夠的空間顯示繪制的半圓效果(本例正常狀態的寬度為30dp)。這裡需要注意的是,當setLayoutParams()調用後,我們要保持A-Z欄在屏幕的位置不變,就要根據情況重新計算每個字母的坐標。

2.在寬度調好之後,要獲取當前被觸摸的字母的在A-Z在豎直線上的坐標(既途中M水平線和A-Z豎直線的交點)作為扭曲半圓的圓心,如圖當前被觸摸的為M,那麼圓心在A-Z欄沒被扭曲時M的位置。

3.在確定好圓心之後,我們要求半徑。如圖,我們把7個字母繪制在了半圓上,那麼A-Z欄豎直線的空白處長度就為,半圓的直徑。可以輕易的看出直徑是7個字母的長度,我們可以很容易的計算出每個字母的高度。再次我們獲得了半徑的值

4.求這七個字母的坐標。首先, 來理一理Android的角度問題,圖中Q所在角度為90,M為180,I為270;得出每個字母的偏移角度分別為:J -- 247.5, K -- 225, L --202.5,

M -- 180, N -- 157.5, O -- 135, P -- 112.5。

在獲得半徑radius, 角度arc ,和圓心坐標O(centerX, centerY)後通過如下公式就可以球道這七個字母的坐標

x = (float) (centerX + radius * Math.cos(arc * Math.PI / 180));
y = (float) (centerY + radius * Math.sin(arc * Math.PI / 180));

二.整個代碼(尊重別人勞動成果,轉載請注明 處(http://blog.csdn.net/u010949962/article/details/42198235):

 

package xu.ye.view.ui;

import java.util.HashMap;

import xu.ye.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;




/**  
 * @author  huangxin
 */
public class QuickAlphabeticBar extends ImageButton {
	
	public static final String TAG = QuickAlphabeticBar;
	
	public static final int DEFAULT_SCREEN_HEIGHT = 800;
	
	public static final int DEFAULT_TEXT_SIZE = 20;
	
	private TextView mDialogText;
	private Handler mHandler;
	private ListView mList;
	private float mHight;
	
	private String[] letters = new String[] { 
			#, 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 HashMap alphaIndexer;
	
	private float centerXY[] = null;
	
	private int singleHeight;
	
	private int height;
	
	private int width;
	
	private float arc = 0;
	
	private float radius;
	
	private float normalWidth;
	private float selectedWidth;
	private boolean isselectedState = false;
	
	private int textSize;
	
	private int startPos = -1;
	private int endPos = -1; 
	
	private Context context;
	
	private float measureTextSize = -1;
	
	private int screenWidth;
	
	private int screenHeight;
	
	
	public QuickAlphabeticBar(Context context) {
		super(context);
		 init(context);
	}

	public QuickAlphabeticBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		 init(context);
	}

	public QuickAlphabeticBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		 init(context);
	}

	public void setScreenWidth(int screenWidth) {
		this.screenWidth = screenWidth;
	}

	public void setScreenHeight(int screenHeight) {
		this.screenHeight = screenHeight;
	}

	private void init(Context context){
		this.context = context;
		//textSize = getTextSizeFormRatio();
		textSize = 10;
		normalWidth = getResources().getDimensionPixelSize(R.dimen.azbar_normal_width);
		selectedWidth = getResources().getDimensionPixelSize(R.dimen.azbar_selected_width);
	}
	
	public void init(Activity ctx) {
		mDialogText = (TextView) ctx.findViewById(R.id.fast_position);
		mDialogText.setVisibility(View.INVISIBLE);
		mHandler = new Handler();
	}
	
	public void setListView(ListView mList) {
		this.mList = mList;
	}

	public void setAlphaIndexer(HashMap alphaIndexer) {
		this.alphaIndexer = alphaIndexer;
	}

	public void setHight(float mHight) {
		this.mHight = mHight;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) 	{
		int act = event.getAction();
		float y = event.getY();
		float x = event.getX();
		final int oldChoose = choose;
		
		singleHeight = height / letters.length;
		radius = 8 * singleHeight / 2;

		int selectIndex = (int) (y / (mHight / letters.length));		
		if (selectIndex > -1 && selectIndex < letters.length) {
			String key = letters[selectIndex];
			if (alphaIndexer.containsKey(key)) {
				int pos = alphaIndexer.get(key);
				if (mList.getHeaderViewsCount() > 0) {
					this.mList.setSelectionFromTop(
							pos + mList.getHeaderViewsCount(), 0);
				} else {
					this.mList.setSelectionFromTop(pos, 0);
				}
			}

			mDialogText.setText(letters[selectIndex]);
			arc = 0;

			if(!isselectedState){
				isselectedState = true;
				//int selected = (int) (centerXY[0] - (radius + paint.measureText(letters[selectIndex])));
				setLayoutParams((int) selectedWidth);
				
			}
		}
		
		switch (act) {
		case MotionEvent.ACTION_DOWN:
			
			showBkg = true;

			if (oldChoose != selectIndex) {
				if (selectIndex >= 0 && selectIndex < letters.length) {
					choose = selectIndex;
					invalidate();
				}
			}

			if (mHandler != null) {
				mHandler.post(new Runnable() {
					@Override
					public void run() {
						if (mDialogText != null
								&& mDialogText.getVisibility() == View.INVISIBLE) {
							mDialogText.setVisibility(VISIBLE);
						}
					}
				});
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if(x < selectedWidth * 0.5 && isselectedState){
				reseAlphabeticBar();
				return super.onTouchEvent(event);
			}
			if (oldChoose != selectIndex) {
				if (selectIndex >= 0 && selectIndex < letters.length) {
					choose = selectIndex;
					invalidate();
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			reseAlphabeticBar();
			break;
		case MotionEvent.ACTION_CANCEL:
			reseAlphabeticBar();
			break;
		default:
			break;
		}

		return super.onTouchEvent(event);
	}
	
	
	private void reseAlphabeticBar(){
		centerXY = null;
		showBkg = false;
		choose = -1;
		isselectedState = false;
		arc = 0;
		setLayoutParams((int) normalWidth);
		if (mHandler != null) {
			mHandler.post(new Runnable() {
				@Override
				public void run() {
					if (mDialogText != null
							&& mDialogText.getVisibility() == View.VISIBLE) {
						mDialogText.setVisibility(INVISIBLE);
						invalidate();
					}
				}
			});
		}
	}

	
	private void setLayoutParams(int width){
		RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(width, 
				RelativeLayout.LayoutParams.MATCH_PARENT);
		lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
		lp.addRule(RelativeLayout.BELOW, R.id.acbuwa_topbar);
		setLayoutParams(lp);
	}
	
	//TODO:
	Paint paint = new Paint();
	boolean showBkg = false;
	int choose = -1;

	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		/*if (showBkg) {//???ñ????????
			canvas.drawColor(Color.parseColor(#b20264));
		}*/

		height = getHeight();
		width = (int) getWidth();
		
		getStartAndEndPosFromArg();
		
		boolean flag = false;
		for (int i = 0; i < letters.length; i++) {
			paint.setColor(getResources().getColor(android.R.color.black));
			paint.setTextSize(textSize);
			Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
			paint.setTypeface(font);
			paint.setAntiAlias(true); 
			
			measureTextSize = paint.measureText(letters[i]);
			
			float xPos, yPos;
			if(isselectedState){
				xPos = selectedWidth - normalWidth / 2 -  measureTextSize / 2;
			}else{
				xPos = normalWidth / 2 - measureTextSize / 2;
			}
			
			yPos = singleHeight * i + singleHeight;
			
			if (i == choose) {
				paint.setColor(Color.parseColor(#00BFFF));
				paint.setFakeBoldText(true);
			}
			
			if((i >= startPos && i <= endPos) && choose != -1 && isselectedState){
				
				if(centerXY == null){
					centerXY = new float[2];
					centerXY[0] = selectedWidth - normalWidth / 2 - measureTextSize / 2;
					centerXY[1] = singleHeight * choose + singleHeight;
				}

				if (!flag) {
					getStartPosFromArg(startPos);
					flag = true;
				}
				
				float[] arcXY = getXYFormArg();
				xPos  =  arcXY[0];
				yPos  =  arcXY[1];

				arc = (float) (arc - 22.5);
				int size = getArgLetterTextSize(i);
				paint.setTextSize(size);
			}
			canvas.drawText(letters[i], xPos, yPos, paint);
			paint.reset();
		}
		centerXY = null;
	}
	
	private void getStartAndEndPosFromArg(){
		if(choose != -1){
			if(choose <= 3){
				startPos = 0;
			}else{
				startPos = choose - 3;
			}

			if(choose - letters.length + 4 <= 0){
				endPos = choose + 3;
			}else{
				endPos = letters.length -1;
			}
		}
	}
	
	private void getStartPosFromArg(int startPos) {

		if (startPos == choose) {
			arc = 180;
		} else if (startPos + 1 == choose) {
			arc = (float) 202.5;
		} else if (startPos + 2 == choose) {
			arc = 225;
		} else if (startPos + 3 == choose) {
			arc = (float) 247.5;
		}
	}

	private int getArgLetterTextSize(int i){
		if(i == choose){
			return textSize + 8;
		}else if(i + 1 == choose || choose + 1 == i){
			return textSize + 6;
		}else if(i + 2== choose || choose + 2 == i){
			return textSize + 4;
		}else if(i + 3== choose || choose + 3 == i){
			return textSize + 4;
		}
		return textSize;
	}
	
	private float[] getXYFormArg(){
		float[] xy = new float[2];	
		xy[0] = (float) (centerXY[0] + radius * Math.cos(arc * Math.PI / 180));
		xy[1] = (float) (centerXY[1] + radius * Math.sin(arc * Math.PI / 180));
		return xy;
	}
	
}


 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved