深入了解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. [email protected]
    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. [email protected]
    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. [email protected]
    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. [email protected]
  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. [email protected]
    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. [email protected]
    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. [email protected]
    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. [email protected]
    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. [email protected]
    99. ????public
      void onShowPress(MotionEvent motionEvent) {
    100. ?
    101. ????}
    102. ?
    103. [email protected]
    104. ????public
      boolean onSingleTapUp(MotionEvent motionEvent) {
    105. ????????return
      false;
    106. ????}
    107. ?
    108. [email protected]
    109. ????public
      boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
    110. ????????return
      false;
    111. ????}
    112. ?
    113. [email protected]
    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. [email protected]
    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. [email protected]
    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. [email protected]
    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. }
时间: 2024-08-07 21:38:10

深入了解view以及自定义控件的相关文章

Android 自定义View(自定义控件)

一.创建一个控件类间接或者直接继承View类 二.创建自定义的样式属性放在attr.xml文件里面,如 <?xml version="1.0" encoding="utf-8"?> <resources> <attr name="titleText" format="string" /> <attr name="titleTextColor" format=&quo

自定义View之自定义控件属性

在自定义一个View的时候,为了让View的功能变得强大点,往往我们需要支持自定义属性来支持显示界面中所需要的效果,比如说:android:textColor="#ffffff"这样定义一个属性,可支持显示不同颜色,那么我们在项目中要如何定义? 首先我们需要在res/values目录下新建个attrs的xml文件当然这个名字是可以自定义的,但是不能重复定义一个属性. <declare-styleable name="myViewAttrs"> <a

自定义控件之直接继承View创建全新视图(二)

自定义控件我们上一节探讨了一种最简单的自定义是直接继承View的子类,实现控件的不同UI视图展示及功能的拓展,在学习新知识前可以温习下之前所学知识-自定义控件之对现有控件拓展(一). ok,在回顾了之前所学的知识之后,现在我们来学习稍微复杂点的自定义控件:今天我们实现一个直接继承于View的全新控件.大家都知道音乐播放器吧,在点击一首歌进行播放时,通常会有一块区域用于显示音频条,我们今天就来学习下,播放器音频条的实现. 首先我们还是先定义一个类,直接继承于View,并重写它的构造方法,并初始化一

Android自定义控件View的探讨

本文转载自:http://www.apkbus.com/forum.php?mod=viewthread&tid=242501&extra=page%3D1 做过了一段时间的安卓开发都会接触到自定义控件,那么对于自定义控件大家都有什么样的看法呢?自定义控件他的优势是明显的,设计他的思想又有哪些呢?会用到什么模式呢?希望大家看了这个文章之后,可以发表自己对于自定义控件的看法和思想,这个帖就是为了跟大家交流而发.下面是我自己的一些看法,大侠们请指导!!! 自定义View: 在这里我们先来了解自

Android自定义控件View(一)

虽然Android API给我们提供了众多控件View来使用,但是鉴于Android的开发性,自然少不了根据需求自定义控件View了.比如说QQ头像是圆形的,但是纵观整个Android控件也找不到一个加载圆形图片的Button或者ImageView,那么咋办?废话,肯定是自定义一个圆形RoundImageView控件啦!这里我们可以继承ImageView重写里面的方法来实现这一效果.还有一种自定义控件是继承View重写里面的onDraw()方法,这类自定义View需要定义自己的属性以备在xml布

自定义控件基础02_下拉刷新_侧拉菜单_自定义属性

自定义控件02 自定义控件 ①,纯粹自定义绘制 ②,在原生的基础上追加功能. 1,下拉刷新功能(继承ListView追加功能)(下拉刷新,加载更多,两个功能) 1.1 下拉刷新 ①创建一个类,继承ListView 创建自定义适配器,设置数据 额外:自定义控件会放到view包下 ②自定义控件的头(即下拉的时候显示的view) 推荐名称initHeaderView();在构造方法中初始化这个头 this.addHeaderView()//添加一个头布局的控件,在listView顶部添加一个头 头部u

Android艺术开发探索第四章——View的工作原理(上)

这章就比较好玩了,主要介绍一下View的工作原理,还有自定义View的实现方法,在Android中,View是一个很重要的角色,简单来说,View是Android中视觉的呈现,在界面上Android提供了一套完整的GUI库,里面有很多控件,但是有时候往往并不能满足于需求,所以只有自定义View了,我们会简单的说下流程,然后再去实践除了View的三大流程之外,View常见的回调方法也是必须掌握的,比如构造方法,onAttach,onVisibilityChanged,onDetach,另外对于一些

Android进阶——自定义View之自己绘制彩虹圆环调色板

引言 前面几篇文章都是关于通过继承系统View和组合现有View来实现自定义View的,刚好由于项目需要实现一个滑动切换LED彩灯颜色的功能,所以需要一个类似调色板的功能,随着手在调色板有效区域滑动,LED彩灯随即显示相应的颜色,也可以通过左右的按钮,按顺序切换显示一组颜色,同时都随着亮度的改变LED彩灯的亮度随即变化,这篇基本上把继承View重绘实现自定义控件的大部分知识总结了下(当然还有蛮多没有涉及到,比如说自适应布局等),源码在Github上 一.继承View绘制自定义控件的通用步骤 自定

【读书笔记】【Android 开发艺术探索】第4章 View 的工作原理

一.基础知识 1.ViewRoot 和 DecorView ViewRoot 对应 ViewRootImpl 类,它是连接 WindowManager 和 DecorView 的纽带,View 的三大流程都是通过 ViewRoot 来完成的.在ActivityThread 中,当 Activity 对象被创建完毕后,会将 DecorView 添加到 Window 中,同时会创建 ViewRoot 对象. DecorView 添加到窗口 Window 的过程. 图片来自https://yq.ali