Android 自定義View——自定義點擊事件


每個人手機上都有通訊錄,這是毫無疑問的,我們通訊錄上有一個控件,在通訊錄的最左邊有一列從”#”到”Z”的字母,我們通過滑動或點擊指定的字母來確定聯系人的位置,進而找到聯系人。我們這一節就通過開發這個控件,來學如何自定義控件的點擊事件。

通訊錄列表查找控件界面繪制

  首先我們需要先將控件的基本布局繪制出來,這里我們不在做詳細的解釋,在《Android 自定義View——自定義View控件 》博客中,我們已經詳細講解了如何繪制自定義控件的布局。通訊錄列表查找控件的布局繪制將只提供思路,不在詳細的說明。先上代碼:

public class MySlider extends View { private int width;//設置高 private int height;//設置高 //字母的寬度和高度 private float textWidth; private float textHeight; private Paint mPaintText;//繪制字母的畫筆 //設置字母數組 private String[] array={"#", "A", "B", "C", "D", "E", "F", "G", "H", "I", "G", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; public MySlider(Context context) { super(context); } public MySlider(Context context, AttributeSet attrs) { super(context, attrs); //初始化畫筆,並設置相關參數。 mPaintText = new Paint(); mPaintText.setColor(Color.GRAY);//畫筆顏色 mPaintText.setAntiAlias(true);//去鋸齒 mPaintText.setTextAlign(Paint.Align.CENTER);//設置字體居中顯示 } /* 重寫onMesure()方法 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);// 獲得控件的寬度 height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);//獲得控件的高度 setMeasuredDimension(width, height);//設置寬和高 //設置字母的高度,字母高度應該是控件的高度除27,然后再減去一個數。 textHeight = height/27f-2; //設置字母的高度 mPaintText.setTextSize(textHeight); } /* 重寫onDraw()方法 */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //求出"M"字母的寬度,因為我們需要將字母設置在控件的最左邊,所以我們需要求出字母的寬度,然后設置。這里我們會求寬度最大的字母的寬度。 textWidth =mPaintText.measureText("M"); //通過循環,將字母繪制在控件上。 for(int i=0; i<27;i++ ){ //繪制文字從數組中獲得, 繪制的位置時控件寬度減去字母寬度width-textWidth,高度是height/27*(i+1) canvas.drawText(""+array[i], width-textWidth, height/27*(i+1), mPaintText); } } }

 

  View界面的繪制思路是:在界面上顯示27個字母,字母豎直排列且顯示在左側,因此需要將繪制的字母的位置的橫坐標設置為width-textWidth,代表控件寬度減去一個字母“M”的寬度,然后然字母居中顯示;字母位置的高度是將空間高度27等分后的數乘以字母的位置。
  這樣控件的基本布局繪制完畢,我們要控件添加點擊了。

通訊錄列表查找控件點擊實現

  實現控件中的點擊,需要在自定義View的類中重寫方法onTouchEvent(),這里需要說一下這個onTouchEvent,它包含多個點擊類型:MotionEvent.ACTION_MOVE,MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP等,看單詞含義便能夠理解這幾種類型,這里不再贅述。

    @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: //獲取屏幕上點擊的坐標 float x=event.getX(); float y = event.getY(); //如果坐標在我們的文字區域內,則將點擊的文字改顏色 if(x>width-2*textWidth){ //點擊后,獲取坐標代表的單詞的含義 index = (int) (y/(height/27)); invalidate();//更新視圖 return true; } break; case MotionEvent.ACTION_UP: //點擊抬起后,回復初始位置。 index=-1; invalidate();//更新視圖 return true; } //這句話不要修改 return super.onTouchEvent(event); }

  這時需要在onDraw()方法中修改如下:

    @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); textWidth =mPaintText.measureText("M"); //添加修改如下,通過index來繪制文本,試問本變顏色。 for(int i=0; i<26;i++ ){ if(index==i){ //將點擊的位置修改顏色 canvas.drawText(""+array[i], width-textWidth, height/27*(i+1), mPaintRed); }else { canvas.drawText(""+array[i], width-textWidth, height/27*(i+1), mPaintText); } } }

 
  在控件中添加了點擊還不夠,如果我們想要在Activity中使用,必須添加點擊事件!

通訊錄列表查找控件添加點擊事件

  可能大家一上來覺得沒思路,不知道怎么寫,不過沒關系,我們可以通過Button點擊事件來類比學習下,首先看Button的點擊事件是如何使用的:

        button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });

 

  Button控件的點擊事件是這樣的,Button對象調用其方法setOnClickListener(OnClickListener listener)來調用點擊事件,該方法中傳入了一個OnClickListener 的對象,這個對象時通過匿名內部類來定義的。創建完匿名內部類后,我們發現還要重寫一個onClick()方法。經過查看Button源碼我們了解到,原來OnClickListener 是Button中的一個內部的接口,該接口包含onClick()方法。通過分析Button的點擊事件,我們掌握了我們需要在我們的自定義View中添加如下幾部分:
    
1. 一個監聽的內部接口,我們給它命名為 OnItemSelectListener。
2. 接口內部有一個onItemSelect的方法,Activity中使用時,通過重寫該方法來實現事件的監聽。
3. 在控件中定義一個OnItemSelectListener接口的對象,並設置set方法。

所以我們對自定義控件進行如下修改:

public class MySlider extends View { private int width; private int height; private float textWidth; private float textHeight; private Paint mPaintText; private Paint mPaintRed; private int index=-1; private String[] array={"#", "A", "B", "C", "D", "E", "F", "G", "H", "I", "G", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}; public MySlider(Context context) { super(context); } public MySlider(Context context, AttributeSet attrs) { super(context, attrs); mPaintText = new Paint(); mPaintText.setColor(Color.GRAY); mPaintText.setAntiAlias(true); mPaintText.setTextAlign(Paint.Align.CENTER); mPaintRed = new Paint(); mPaintRed.setColor(Color.BLUE); mPaintRed.setAntiAlias(true); mPaintRed.setTextAlign(Paint.Align.CENTER); } //定義一個接口對象listerner private OnItemSelectListener listener; //獲得接口對象的方法。 public void setOnItemSelectListener(OnItemSelectListener listener) { this.listener = listener; } //定義一個接口 public interface OnItemSelectListener{ public void onItemSelect(int index, String indexString); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(width, height); textHeight = height/27f-2; mPaintText.setTextSize(textHeight); mPaintRed.setTextSize(textHeight); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); textWidth =mPaintText.measureText("M"); for(int i=0; i<26;i++ ){ if(index==i){ canvas.drawText(""+array[i], width-textWidth, height/27*(i+1), mPaintRed); }else { canvas.drawText(""+array[i], width-textWidth, height/27*(i+1), mPaintText); } } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_DOWN: float x=event.getX(); float y = event.getY(); if(x>width-2*textWidth){ index = (int) (y/(height/27)); //此處有增加,當屏幕被點擊后,將參數傳入。 if(listener!=null){ listener.onItemSelect(index, array[index]); } invalidate(); return true; } break; case MotionEvent.ACTION_UP: index=-1; invalidate(); return true; } return super.onTouchEvent(event); } }

  點擊事件定義玩了,我們來看看如何使用……

通訊錄列表查找控件的使用

1. 在布局中添加控件:

<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" tools:context="com.example.administrator.mywidgetdemo.activity.BitmapActivity"> <com.example.administrator.mywidgetdemo.event.MySlider android:id="@+id/mysilider" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/textview" android:layout_width="200dp" android:layout_height="200dp" android:textSize="100sp" android:text="A" android:layout_centerInParent="true" android:gravity="center" /> </RelativeLayout>

 

2. Activity中獲取控件對象,並監聽點擊事件:

public class BitmapActivity extends Activity { private TextView mTextView; private MySlider mMySilder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_bitmap); mTextView = (TextView) findViewById(R.id.textview); mMySilder = (MySlider) findViewById(R.id.mysilider); mMySilder.setOnItemSelectListener(new MySlider.OnItemSelectListener() { @Override public void onItemSelect(int index, String indexString) { mTextView.setText(indexString); } }); } }

結果如下:

這里寫圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM