Android内置了很多View,包括:

  • TextView
  • EditText
  • Chronometer
  • ListView
  • Spinner
  • Button
  • ToggleButton
  • ImageButton
  • CheckBox
  • RedioButton
  • ViewFlipper
  • VideoView
  • QuickContactBadge
  • ViewPager

关于View更多的信息,可以参考:http://developer.android.com/guide/tutorials/views/index.html

创建自定义View的三种方式

总的来说,有三种方法来创建新的View:

  • 修改已有的View。
  • 使用多个已有的View组成新的复合View
  • 从头新建一个View

修改已有的View

创建某种View的子类并重写父类的方法,即可通过修改已有View来创建自定义的View,例如:

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.TextView;
public class MyTextView extends TextView {
  public MyTextView (Context context, AttributeSet attrs, int defStyle)
  {
  super(context, attrs, defStyle);
  }
  public MyTextView (Context context) {
  Super(context);
  }
  public MyTextView (Context context, AttributeSet attrs) {
  super(context, attrs);
  }
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
  [ ... Perform some special processing ... ]
  [ ... based on a particular key press ... ]
  // Use the existing functionality implemented by
  // the base class to respond to a key press event.
  return super.onKeyDown(keyCode, keyEvent);
  }
}

创建复合控件View

复合控件由多个View组成,是ViewGroup的子类。通过继承ViewGroup并重写父类的构造函数,在构造过程中inflate某个Layout,是常用的生成复合控件的方法之一,例如:

public class ClearableEditText extends LinearLayout {
  EditText editText;
  Button clearButton;
  public ClearableEditText(Context context) {
  super(context);
  // Inflate the view from the layout resource.
  String infService = Context.LAYOUT_INFLATER_SERVICE;
  LayoutInflater li;
  li = (LayoutInflater)getContext().getSystemService(infService);
  li.inflate(R.layout.clearable_edit_text, this, true);
  // Get references to the child controls.
  editText = (EditText)findViewById(R.id.editText);
  clearButton = (Button)findViewById(R.id.clearButton);
  // Hook up the functionality
  hookupButton();
  }
}

配置文件:

<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
  android:orientation=”vertical”
  android:layout_width=”match_parent”
  android:layout_height=”wrap_content”>
  <EditText
  android:id=”@+id/editText”
  android:layout_width=”match_parent”
  android:layout_height=”wrap_content”
  />
  <Button
  android:id=”@+id/clearButton”
  android:layout_width=”match_parent”
  android:layout_height=”wrap_content”
  android:text=”Clear”
  />
</LinearLayout>

使用Layout文件创建复合控件

使用<include>标签可以方便地复用已有的复合View,例如:

<include layout=”@layout/clearable_edit_text”
  android:id=”@+id/add_new_entry_input”
  android:layout_width=”match_parent”
  android:layout_height=”wrap_content”
  android:layout_gravity=”top”/>

创建自定义View

通过继承View或SurfaceView,程序员就可以实现自定义的View。View类有一个Canvas对象,可以在上面绘制自己的UI。SurfaceView类有一个Surface对象,Surface支持后台线程绘制,并可以使用OpenGL进行绘制。对于需要经常重绘并且不需要3D效果的UI,推荐使用轻量级的View来实现。

创建新的View

View中的OnMeasure()方法用于确定View的长和高,OnDraw()方法则用于绘制图形,下面是创建一个自定义View的示例代码:

public class MyView extends View {
  // Constructor required for in-code creation
  public MyView(Context context) {
    super(context);
  }
  // Constructor required for inflation from resource file
  public MyView (Context context, AttributeSet ats, int defaultStyle) {
    super(context, ats, defaultStyle );
  }
  //Constructor required for inflation from resource file
  public MyView (Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  @Override
  protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
    int measuredHeight = measureHeight(hMeasureSpec);
    int measuredWidth = measureWidth(wMeasureSpec);
    // MUST make this call to setMeasuredDimension or you will cause a runtime exception when the control is laid out.
    setMeasuredDimension(measuredHeight, measuredWidth);
  }
  private int measureHeight(int measureSpec) {
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    [ ... Calculate the view height ... ]
    return specSize;
  }
  private int measureWidth(int measureSpec) {
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    [ ... Calculate the view width ... ]
    return specSize;
  }
  @Override
  protected void onDraw(Canvas canvas) {
    [ ... Draw your visual interface ... ]
  }
}

重写onDraw()方法

@Override
protected void onDraw(Canvas canvas) {
  // Get the size of the control based on the last call to onMeasure.
  int height = getMeasuredHeight();
  int width = getMeasuredWidth();
  // Find the center
  int px = width/2;
  int py = height/2;
  // Create the new paint brushes.
  // NOTE: For efficiency this should be done in the views’s constructor
  Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  mTextPaint.setColor(Color.WHITE);
  // Define the string.
  String displayText = “Hello World!”;
  // Measure the width of the text string.
  float textWidth = mTextPaint.measureText(displayText);
  // Draw the text string in the center of the control.
  canvas.drawText(displayText, px-textWidth/2, py, mTextPaint);
}

重写OnMeasure()方法

Android中View的默认大小是100*100像素,重写OnMeasure()方法,可以实现自定义长和宽:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int measuredHeight = measureHeight(heightMeasureSpec);
  int measuredWidth = measureWidth(widthMeasureSpec);
  setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
  // Return measured widget height.
}
private int measureWidth(int measureSpec) {
  // Return measured widget width.
}

处于效率的考虑,measureSpec和measureSpec直接作为int参数传给了onMeasure(),但在使用之前,首先要decode:

int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);

下面的代码是一个典型的处理Measure的例子:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int measuredHeight = measureHeight(heightMeasureSpec);
  int measuredWidth = measureWidth(widthMeasureSpec);
  setMeasuredDimension(measuredHeight, measuredWidth);
}
private int measureHeight(int measureSpec) {
  int specMode = MeasureSpec.getMode(measureSpec);
  int specSize = MeasureSpec.getSize(measureSpec);
  // Default size if no limits are specified.
  int result = 500;
  if (specMode == MeasureSpec.AT_MOST) {
    // Calculate the ideal size of your control within this maximum size.
    // If your control fills the available space return the outer bound.
    result = specSize;
  } else if (specMode == MeasureSpec.EXACTLY) {
    // If your control can fit within these bounds return that value.
    result = specSize;
  }
  return result;
}
private int measureWidth(int measureSpec) {
  int specMode = MeasureSpec.getMode(measureSpec);
  int specSize = MeasureSpec.getSize(measureSpec);
  // Default size if no limits are specified.
  int result = 500;
  if (specMode == MeasureSpec.AT_MOST) {
    // Calculate the ideal size of your control within this maximum size.
    // If your control fills the available space return the outer bound.
    result = specSize;
  } else if (specMode == MeasureSpec.EXACTLY) {
    // If your control can fit within these bounds return that value.
    result = specSize;
  }
  return result;
}

处理UI交互事件

通过重写类似下面列举的这些方法,可以处理常见的UI交互事件:

  • onKeyDown
  • onKeyUp
  • onTrackballEvent
  • onTouchEvent

Android 4学习(9):用户界面 - THE ANDROID WIDGET TOOLBOX的更多相关文章

  1. Android Sip学习(三)Android Voip实现

    Android Sip学习(三)Android Voip实现   Android Sip学习(准备知识)SIP 协议完整的呼叫流程 Android Sip学习(一)Android 2.3 APIs S ...

  2. Android FrameWork学习(二)Android系统源码调试

    通过上一篇 Android FrameWork学习(一)Android 7.0系统源码下载\编译 我们了解了如何进行系统源码的下载和编译工作. 为了更进一步地学习跟研究 Android 系统源码,今天 ...

  3. android菜鸟学习笔记5----第一个android程序

    程序功能:点击一个按钮,然后弹出一个提示信息 Step 1:在eclipse中新建一个android application project,在创建过程中不勾选create activity,这样就创 ...

  4. Android开发学习总结(二)——使用Android Studio搭建Android集成开发环境

    有很长一段时间没有更新博客了,最近实在是太忙了,没有时间去总结,现在终于可以有时间去总结一些Android上面的东西了,很久以前写过这篇关于使用Android Studio搭建Android集成开发环 ...

  5. android开发学习 ------- 【转】 android中的单例模式 (详解)

    https://blog.csdn.net/u011418943/article/details/60139644     这篇文章 前因后果 都说出来了 ,值得学习. https://blog.cs ...

  6. Android开发学习之三——第一个Android程序

    下面我们建立第一个Android程序. 打开Eclipse,开始如下步骤: 1.File ==> New ==> Android Application Project 出现如下窗口: 2 ...

  7. 吴裕雄--天生自然Android开发学习:下载安装android stuio集成开发工具

    下载链接: https://developer.android.google.cn/index.html

  8. Android 开发学习进程0.17 Android资源文件selector textview显示两种不同字体

    selector 是安卓资源文件的一种,它可以使按钮等实现不同状态下的不同UI,不用在代码中实现,而使用方式有两种,一种在color文件下 创建.xml可以使按钮等字体在不同状态下的变化,其二是在dr ...

  9. android开发学习 ------- 【转】 android事件分发机制 和 自定义view涉及的事件分发

    参考  https://blog.csdn.net/carson_ho/article/details/54136311   ,写的很完美,原理入门的一篇博客,看这一篇就够了 https://www. ...

  10. android开发学习 ------- 【转】 android中的线程池

    线程很常见 , https://blog.csdn.net/seu_calvin/article/details/52415337    参考,保证能看懂.

随机推荐

  1. 005——VUE中的v-text与v-html的使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. hibernate 延迟加载和抓取策略

    一.延迟加载 1.简单查询get,load 针对对象本身延迟或即时 当使用load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load ...

  3. html03表单

    <!DOCTYPE HTML> <html> <head> <title>用户登录的表单</title> </head> < ...

  4. javascript: what can javascript do?

    1.Javascript can change html content <!DOCTYPE html> <html> <body> <h2>What ...

  5. Arcgis for Javascript之统计图的实现

    首先,截个图给大家看看效果: 初始化状态 放大后的状态 点击选中后的状态 如上图所示,一般的涉及到的地图的统计涉及到上述所展示的三个状态:1.初始化状态:2.缩放后的状态:3.点击选中显示详情状态.第 ...

  6. JS返回上一页并刷新

    window.history.go(-1);//返回上一页不刷新 window.location.href = document.referrer;//返回上一页并刷新

  7. svn: E220001: 遇到不可读的路径;拒绝访问。

    在客户端试图 svn merge 总是报svn: E220001: 遇到不可读的路径:拒绝访问.这个错误 提示 : SVN 遇到不可读的路径:拒绝访问. 英文是: Unreadable path en ...

  8. Solr初步使用

    参考此文:https://blog.csdn.net/frankcheng5143/article/details/71159936

  9. PHP读取文件函数fread,fgets,fgetc,file_get_contents和file函数的使用总结

    fread().fgets().fgetc().file_get_contents() 与 file() 函数用于从文件中读取内容. 1.fread() fread()函数用于读取文件(可安全用于二进 ...

  10. HihoCoder 1183 : 连通性一·割边与割点(模板)

    连通性一·割边与割点 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 还记得上次小Hi和小Ho学校被黑客攻击的事情么,那一次攻击最后造成了学校网络数据的丢失.为了避免再次 ...