深入了解view以及自定义控件

参考文章: http://blog.csdn.net/guolin_blog/article/details/12921889 Android LayoutInflater原理分析,带你一步步深入了解View(一) Android自定义View的实现方法,带你一步步深入了解View(四)

这里面总共有三种自定义控件:

自绘控件、组合控件、继承控件

 

  1. 自绘控件
    1. package com.example.DefineView1;
    2.  
    3. import android.content.Context;
    4. import android.graphics.Canvas;
    5. import android.graphics.Color;
    6. import android.graphics.Paint;
    7. import android.graphics.Rect;
    8. import android.util.AttributeSet;
    9. import android.view.View;
    10.  
    11. /**
    12.  * Created by zhuxuekui on 2015/5/18.
    13.  */
    14.  
    15. /**
    16.  * 自定义组合控件之 自绘控件
    17.  */
    18. public class CounterView extends View implements View.OnClickListener {
    19.  
    20.     private Paint mPaint;
    21.     private Rect mBounds;
    22.     private int mCount;
    23.     public CounterView(Context context, AttributeSet attrs) {
    24.         super(context, attrs);
    25.         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    26.         mBounds = new Rect();
    27.         setOnClickListener(this);
    28.  
    29.     }
    30.  
    31.     @Override
    32.     protected void onDraw(Canvas canvas) {
    33.         super.onDraw(canvas);
    34.         mPaint.setColor(Color.BLUE);
    35.         canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
    36.         mPaint.setColor(Color.YELLOW);
    37.         mPaint.setTextSize(30);
    38.         String text = String.valueOf(mCount);
    39.         mPaint.getTextBounds(text,0,text.length(),mBounds);// 获取文字区域(其实是一个mBounds)的宽度与高度,然后回调。
    40.         float textWidth = mBounds.width();
    41.         float textHeight = mBounds.height();
    42.         canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2
    43.                 + textHeight / 2, mPaint); //在画布上绘制文字
    44.     }
    45.  
    46.     @Override
    47.     public void onClick(View view) {
    48.           mCount++;
    49.           invalidate(); //重绘
    50.     }
    51. }

    在CounterView中,我们先初始化一些数据,然后设置view的点击事件。然后调用onclick方法,这里面有invalidate方法,重绘命令。然后调用ondraw方法,开始进行视图的绘制。

     

    1. package com.example.DefineView1;
    2.  
    3. import android.app.Activity;
    4. import android.os.Bundle;
    5.  
    6. public class MyActivity extends Activity {
    7.     /**
    8.      * Called when the activity is first created.
    9.      */
    10.     @Override
    11.     public void onCreate(Bundle savedInstanceState) {
    12.         super.onCreate(savedInstanceState);
    13.         setContentView(R.layout.main);
    14.     }
    15. }

 

 

  1. 组合控件

程序结构:

  1. package com.example.DefineView2;
  2.  
  3. import android.app.Activity;
  4. import android.content.Context;
  5. import android.util.AttributeSet;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.widget.Button;
  9. import android.widget.FrameLayout;
  10. import android.widget.TextView;
  11.  
  12. /**
  13.  * Created by zhuxuekui on 2015/5/18.
  14.  */
  15. public class TitleView extends FrameLayout {
  16.  
  17.     private Button leftButton;
  18.     private TextView titleText;
  19.     public TitleView(Context context, AttributeSet attrs) {
  20.         super(context, attrs);
  21.         LayoutInflater.from(context).inflate(R.layout.title, this);
  22.         titleText = (TextView)findViewById(R.id.title_text);
  23.         leftButton = (Button)findViewById(R.id.button_left);
  24.         leftButton.setOnClickListener(new OnClickListener() {
  25.             @Override
  26.             public void onClick(View view) {
  27.                 ((Activity)getContext()).finish();
  28.             }
  29.         });
  30.     }
  31.  
  32.     public void setTitleText(String text)
  33.     {
  34.         titleText.setText(text);
  35.     }
  36.  
  37.     public void setLeftButtonText(String text)
  38.     {
  39.         leftButton.setText(text);
  40.     }
  41.  
  42.     public void setLeftButtonListener(OnClickListener l)
  43.     {
  44.         leftButton.setOnClickListener(l);
  45.     }
  46. }

首先我们定义title.xml下面的,然后定义TextView 继承FragmentLayout ,代码如上面的所示。里面我们对xml里面的控件进行初始化,设置事件都可以。

 

 

 

 

  1. 继承控件

    截图:

    程序结构:

     

     

    1)增加的小按钮,只有一个button,没有布局

    Delete_button.xml 子定义的listview里面增加的内容

     

    2)编写我们自己的mylistview类

    Mylistview

    1. package com.example.DefineView3;
    2.  
    3. import android.content.Context;
    4. import android.util.AttributeSet;
    5. import android.view.*;
    6. import android.widget.ListView;
    7. import android.widget.RelativeLayout;
    8.  
    9. /**
    10.  * Created by zhuxuekui on 2015/5/18.
    11.  */
    12. public class MyListView extends ListView implements View.OnTouchListener,GestureDetector.OnGestureListener {
    13.     private GestureDetector gestureDetector;
    14.     private OnDeleteListener listener;
    15.     private View deleteButton;
    16.     private ViewGroup itemLayout;
    17.     private int selectedItem;
    18.     private boolean isDeleteShown;
    19.  
    20.     public MyListView(Context context, AttributeSet attrs) {
    21.         super(context, attrs);
    22.         gestureDetector = new GestureDetector(getContext(),this);
    23.         setOnTouchListener(this);
    24.     }
    25.  
    26.     public void setOnDeleteListener(OnDeleteListener l)
    27.     {
    28.         listener = l;
    29.     }
    30.  
    31.  
    32.  
    33.  
    34.     @Override
    35.     public boolean onTouch(View view, MotionEvent motionEvent) {
    36.         if(isDeleteShown){
    37.             itemLayout.removeView(deleteButton);
    38.             deleteButton = null;
    39.             isDeleteShown = false;
    40.             return false;
    41.         }else{
    42.             return gestureDetector.onTouchEvent(motionEvent);
    43.         }
    44.     }
    45.  
    46. //下面几个方法是OnTouchEvent的事件处理
    47.  
    48.     /**
    49.      * 手指按下事件处理
    50.      * @param motionEvent
    51.      * @return
    52.      */
    53.     @Override
    54.     public boolean onDown(MotionEvent motionEvent) {
    55.         if(!isDeleteShown)
    56.         {
    57.             selectedItem = pointToPosition((int)motionEvent.getX(),(int)motionEvent.getY());//判断当前选中的是listview的第几行
    58.         }
    59.         return false;
    60.     }
    61.  
    62.     /**
    63.      * 快速滑动事件处理
    64.      * @param motionEvent
    65.      * @param motionEvent1
    66.      * @param X
    67.      * @param Y
    68.      * @return
    69.      */
    70.     @Override
    71.     public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float X, float Y) {
    72.  
    73.         // 快速滑动到某一行上,加载布局deleteButton,并将删除按钮添加到当前选中的那一行item中
    74.         if(!isDeleteShown && Math.abs(X) > Math.abs(Y)){
    75.             deleteButton = LayoutInflater.from(getContext()).inflate(R.layout.delete_button,null);
    76.             deleteButton.setOnClickListener(new OnClickListener() {
    77.                 @Override
    78.                 public void onClick(View view) {
    79.                     //当点击了删除按钮,我们就去回调onDeleteListener的onDelete()方法
    80.                     itemLayout.removeView(deleteButton);
    81.                     deleteButton = null;
    82.                     isDeleteShown = false;
    83.                     listener.onDelete(selectedItem);
    84.                 }
    85.             });
    86.  
    87.             itemLayout = (ViewGroup)getChildAt(selectedItem - getFirstVisiblePosition());
    88.             RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
    89.             params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    90.             params.addRule(RelativeLayout.CENTER_VERTICAL);
    91.             itemLayout.addView(deleteButton, params);
    92.             isDeleteShown = true;
    93.         }
    94.  
    95.         return false;
    96.     }
    97.  
    98.     @Override
    99.     public void onShowPress(MotionEvent motionEvent) {
    100.  
    101.     }
    102.  
    103.     @Override
    104.     public boolean onSingleTapUp(MotionEvent motionEvent) {
    105.         return false;
    106.     }
    107.  
    108.     @Override
    109.     public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
    110.         return false;
    111.     }
    112.  
    113.     @Override
    114.     public void onLongPress(MotionEvent motionEvent) {
    115.  
    116.     }
    117.  
    118.     public interface OnDeleteListener{
    119.         void onDelete(int index);
    120.     }
    121. }

    先去执行构造方法,创建gestureDetector手势捕捉监听程序,以及注册了ontouch监听。当我们按下的时候,触屏就算,程序执行到onTouch() 中,如果删除按钮已经显示我们删除掉图标,如果没有显示删除图标,我们使用gestureDetector来处理当前手势。然后我们执行gestureDetector.onTouchEvent(motionEvent) 。这里面包含多个方法,首先是onDown(),捕捉我们的手指按在了哪一行,我们记录下,滑动的时候,执行onfling(),

    当按钮没有显示,然后我们去加载delete_button.xml此布局,然后并将其现在在listview当前选择的那一行上面,当我们点击删除图标的时候,执行回调方法,执行相应的逻辑。这部分逻辑在主界面中完成。

     

     

    3)建立listview里面的子项

    至此,新建上面的mylistview里面的每一个子项,my_list_view_item.xml.

    My_list_view_item.xml listview 的子项

     

     

    4)建立适配器类,继承ArrayAdapter

     

    下一步就是新建适配器类

    1. package com.example.DefineView3;
    2.  
    3. import android.content.Context;
    4. import android.view.LayoutInflater;
    5. import android.view.View;
    6. import android.view.ViewGroup;
    7. import android.widget.ArrayAdapter;
    8. import android.widget.TextView;
    9.  
    10. import java.util.List;
    11.  
    12. /**
    13.  * Created by zhuxuekui on 2015/5/18.
    14.  */
    15. public class MyAdapter extends ArrayAdapter<String> {
    16.  
    17.     public MyAdapter(Context context, int resource, List<String> objects) {
    18.         super(context, resource, objects);
    19.     }
    20.  
    21.     @Override
    22.     public View getView(int position, View convertView, ViewGroup parent) {
    23.         View view;
    24.         if(convertView == null)
    25.         {
    26.             view = LayoutInflater.from(getContext()).inflate(R.layout.my_list_view_item,null);
    27.         }else{
    28.             view = convertView;
    29.         }
    30.  
    31.         TextView textView = (TextView)view.findViewById(R.id.text_view);
    32.         textView.setText(getItem(position));
    33.         return view;
    34.     }
    35. }

    这一步主要就是重载ArrayAdapter,并重写构造方法和getview方法。

     

    5)编写主界面的布局,使用自定义的listview控件

     

    Mail.xml 布局自定义的listview

     

     

    6)写主界面myactivity.java

    1. package com.example.DefineView3;
    2.  
    3. import android.app.Activity;
    4. import android.os.Bundle;
    5.  
    6. import java.util.ArrayList;
    7. import java.util.List;
    8.  
    9.  
    10. /**
    11.  * 自定义控件3 之 继承控件
    12.  */
    13. public class MyActivity extends Activity {
    14.  
    15.     private MyListView myListView;
    16.     private MyAdapter adapter;
    17.     private List<String> contentList = new ArrayList<String>();
    18.  
    19.     /**
    20.      * Called when the activity is first created.
    21.      */
    22.     @Override
    23.     public void onCreate(Bundle savedInstanceState) {
    24.         super.onCreate(savedInstanceState);
    25.         setContentView(R.layout.main);
    26.         initList();
    27.         myListView = (MyListView)findViewById(R.id.my_list_view);
    28.         myListView.setOnDeleteListener(new MyListView.OnDeleteListener() {
    29.             @Override
    30.             public void onDelete(int index) {
    31.                 contentList.remove(index);
    32.                 adapter.notifyDataSetChanged();
    33.             }
    34.         });
    35.  
    36.         adapter = new MyAdapter(this,0,contentList);
    37.         myListView.setAdapter(adapter);
    38.     }
    39.  
    40.     private void initList(){
    41.         contentList.add("Content Item 1");
    42.         contentList.add("Content Item 2");
    43.         contentList.add("Content Item 3");
    44.         contentList.add("Content Item 4");
    45.         contentList.add("Content Item 5");
    46.         contentList.add("Content Item 6");
    47.         contentList.add("Content Item 7");
    48.         contentList.add("Content Item 8");
    49.         contentList.add("Content Item 9");
    50.         contentList.add("Content Item 10");
    51.         contentList.add("Content Item 11");
    52.         contentList.add("Content Item 12");
    53.         contentList.add("Content Item 13");
    54.         contentList.add("Content Item 14");
    55.         contentList.add("Content Item 15");
    56.         contentList.add("Content Item 16");
    57.         contentList.add("Content Item 17");
    58.         contentList.add("Content Item 18");
    59.         contentList.add("Content Item 19");
    60.         contentList.add("Content Item 20");
    61.     }
    62. }
原文地址:https://www.cnblogs.com/zhuxuekui/p/4513427.html