zoukankan      html  css  js  c++  java
  • 深入了解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. }
  • 相关阅读:
    Android Studio教程-创建第一个项目Hello World
    java打jar包的几种方式详解
    低学历者如何逆袭
    strlen, wcslen, _mbslen, _mbslen_l, _mbstrlen, _mbstrlen_l, setlocale(LC_CTYPE, "Japanese_Japan")(MSDN的官方示例)
    select, poll, epoll
    KVM虚拟化知识的一些笔记
    在Windows系统上以C++打印出当前活动用户的环境变量
    日志组件解析
    Angular2案例rebirth开源
    视图
  • 原文地址:https://www.cnblogs.com/zhuxuekui/p/4513427.html
Copyright © 2011-2022 走看看