編輯:關於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;
}
}
實例講解Android中ContentProvider組件的使用方法
ContentProvider基本使用為了在應用程序之間交換數據,android提供了ContentProvider,ContentProvider是不同應用程序之間進行
Android學習教程之動態GridView控件使用(6)
本文實例為大家分享了Android動態GridView控件使用的具體代碼,供大家參考,具體內容如下MainActivity.java代碼:package siso.hah
Android基礎入門教程——2.4.7 構建一個可復用的自定義BaseAdapter
Android基礎入門教程——2.4.7 構建一個可復用的自定義BaseAdapter標簽(空格分隔): Android基礎入門教程本節引言: 如
局部加權回歸、欠擬合、過擬合 - Andrew Ng機器學習公開課筆記1.3
本文主要講解局部加權(線性)回歸。在講解局部加權線性回歸之前,先講解兩個概念:欠擬合、過擬合,由此引出局部加權線性回歸算法。 欠擬合、過擬合如下圖中三個擬合模型