zoukankan      html  css  js  c++  java
  • android 之 custom view(一)

      android在两个基本布局类ViewViewGroup的基础上提供了成熟而又强大的构建UI组件模型。首先,平台包含了各种预先构建的ViewViewGroup,他们被称为widget和布局。你可以用他们构建你的UI

      一些可用的widget包括Button,TextView,EditText,ListView,CheckBox,RadioButton,Gallery,Spiner,和更多特殊用户的AutoComploteTextView,ImageSwitcher,TextSwitcher.

      一些可以使用的布局如LinearLayout,FramwLayout,RelativeLayout等。

      如果已有的widgets和布局不能满足你的要求,你可以创建你自己的View子类。如果你仅仅需要对一些已存在的widget所一些小小的调整,你可以创建他们的子类来重写一些方法。

      创建你自己的View的子类可以精确地控制界面元素的外观和功能。对于自定义的View组件,通常有下面几种处理方式:

      1.你可以创建一个完全自定义渲染的view类型,例如‘音量控制’旋钮使用2D图形,它类似于一个模拟电子控制。

      2.你可以组合一组view组件来构成一个新的、单一的组件。也许类似一个ComboBox(弹出列表和自由文本字段的组合),双窗口的控制选择器(),以此类推。

      3.你可以采用一种方式,类似覆盖EditText组件展示在屏幕上(记事本教程使用它效果不错,创建了一个具有线条的页面)

      4.你可以捕获其他的像按键事件和按照自定义的方式处理他们(事件)

      下面就说说如何创建自定义视图和应用程序中使用它们。一些常用的基本做法:

      1.扩展已有Viewclass或者View的子类。

      2.覆盖重写父类的一些方法,这些方法通常是以‘on'开头的方法。比如:onDraw,onMeasure(),onKeyDown,等。

      3.使用你的新的扩展类。一旦完成,你的新的扩展类可以使用在代替你扩展类的基类的地方。

      提示:扩展类通常作为使用它们的活动内的内部类,这样父类可以方方便的控制他。为了扩展它的使用范围,你同样可以设置它为public.

    完全自定义组件:

      完全自定义组件可以创建你想要的任何图形组件。你可以根据你的想象(组件屏幕尺寸,组件的处理能力)创建你任何喜欢的(组件的)外观和行为。

    创建一个完全自定义的组件步骤:

      a.继承View类;b.你可以提供一个构造方法,这个构造方法可以从XML文件获得组件的属性和参数。你可以定义你组件的属性和参数;c.你可以为你的组件创建自己的事件监听器,属性访问与修改,甚至更富在的组件行为;d.下面这个就比较重要了。你可以覆盖重写onMeasure(),onDraw()。默认情况下:onDraw()什么也不做,onMeasure()会设置一个100100的尺寸。e.你或许需要覆盖重写View其他的方法或者定义你自己的方法。

      

      掌握完全自定义组件最重要的两点:首先你了解组件被显示出来的所走的流程,也就是View类哪些方法被调用。其次就是属性与参数的定义。下图我自认为很重要,要好好理解:

     

      上面方法重要的两个:onDraw,onMeasure。那就好好说说他们吧。onDraw()方法传递了一个Canvas对象,这个对象你可以实现任何你想要的:2D图形,其他标准或者自定义的组件,文本风格,或者你其它你想要的(注意:这个并不适应3D图形。如果那样,你必须继承SurfaceView,在一个独立的线程绘画,参考GLSurfaceViewActivity sample).

       onMeasure就复杂了,简单的说就是决定你组件size的地方。这个决定的size不光可以是你组件本身size,还包括孩子组件的size(这个是很多人忽略的问题)。它有两个参数,这个两个参数是跟你的组件的layout_widthlayout_height有关系。在你计算出你的组件size之后,你就可以使用setMeasuredDimension()ok了。为什么呢,其实view的调用程序也就是:measure->onMeasure->setMeasuredDimension.

       下面就说说一些简单的例子吧:

      首先第一个就是samples里面的例子,因为是官方的,这个 必须说说,源代码如下:

    LabelView.java
    /**
    * Example of how to write a custom subclass of View. LabelView
    * is used to draw simple text views. Note that it does not handle
    * styled text or right-to-left writing systems.
    *
    */
    public class LabelView extends View {
    private Paint mTextPaint;
    private String mText;
    private int mAscent;

    /**
    * Constructor. This version is only needed if you will be instantiating
    * the object manually (not from a layout XML file).
    *
    @param context
    */
    public LabelView(Context context) {
    super(context);
    initLabelView();
    }

    /**
    * Construct object, initializing with any attributes we understand from a
    * layout file. These attributes are defined in
    * SDK/assets/res/any/classes.xml.
    *
    *
    @see android.view.View#View(android.content.Context, android.util.AttributeSet)
    */
    public LabelView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initLabelView();

    TypedArray a = context.obtainStyledAttributes(attrs,
    R.styleable.LabelView);

    CharSequence s = a.getString(R.styleable.LabelView_text);
    if (s != null) {
    setText(s.toString());
    }

    // Retrieve the color(s) to be used for this view and apply them.
    // Note, if you only care about supporting a single color, that you
    // can instead call a.getColor() and pass that to setTextColor().
    setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));

    int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
    if (textSize > 0) {
    setTextSize(textSize);
    }

    a.recycle();
    }

    private final void initLabelView() {
    mTextPaint = new Paint();
    mTextPaint.setAntiAlias(true);
    mTextPaint.setTextSize(16);
    mTextPaint.setColor(0xFF000000);
    setPadding(3, 3, 3, 3);
    }

    /**
    * Sets the text to display in this label
    *
    @param text The text to display. This will be drawn as one line.
    */
    public void setText(String text) {
    mText = text;
    requestLayout();
    invalidate();
    }

    /**
    * Sets the text size for this label
    *
    @param size Font size
    */
    public void setTextSize(int size) {
    mTextPaint.setTextSize(size);
    requestLayout();
    invalidate();
    }

    /**
    * Sets the text color for this label.
    *
    @param color ARGB value for the text
    */
    public void setTextColor(int color) {
    mTextPaint.setColor(color);
    invalidate();
    }

    /**
    *
    @see android.view.View#measure(int, int)
    */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(measureWidth(widthMeasureSpec),
    measureHeight(heightMeasureSpec));
    }

    /**
    * Determines the width of this view
    *
    @param measureSpec A measureSpec packed into an int
    *
    @return The width of the view, honoring constraints from measureSpec
    */
    private int measureWidth(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
    // We were told how big to be
    result = specSize;
    } else {
    // Measure the text
    result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
    + getPaddingRight();
    if (specMode == MeasureSpec.AT_MOST) {
    // Respect AT_MOST value if that was what is called for by measureSpec
    result = Math.min(result, specSize);
    }
    }

    return result;
    }

    /**
    * Determines the height of this view
    *
    @param measureSpec A measureSpec packed into an int
    *
    @return The height of the view, honoring constraints from measureSpec
    */
    private int measureHeight(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    mAscent = (int) mTextPaint.ascent();
    if (specMode == MeasureSpec.EXACTLY) {
    // We were told how big to be
    result = specSize;
    } else {
    // Measure the text (beware: ascent is a negative number)
    result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
    + getPaddingBottom();
    if (specMode == MeasureSpec.AT_MOST) {
    // Respect AT_MOST value if that was what is called for by measureSpec
    result = Math.min(result, specSize);
    }
    }
    return result;
    }

    /**
    * Render the text
    *
    *
    @see android.view.View#onDraw(android.graphics.Canvas)
    */
    @Override
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent, mTextPaint);
    }
    }
    attrs.xml
    17 <resources>
    18 <!-- These are the attributes that we want to retrieve from the theme
    19 in app/PreferencesFromCode.java
    -->
    30 <declare-styleable name="LabelView">
    31 <attr name="text" format="string" />
    32 <attr name="textColor" format="color" />
    33 <attr name="textSize" format="dimension" />
    34 </declare-styleable>
    35 </resources>

      这里它自定义了一个View组建LabelView.它只有三个属性:text,textColor,textSize,及相关方法。在第二个构造函数里,获取xml属性值做一些处理。然后就是onMeasure,onDraw,这个两个没有什么好说的,上面讲了的。


  • 相关阅读:
    $(this)和this 区别
    文本溢出显示省略标记'...'的bug
    web中常用的20种字体 (share)
    Underscore.js 的模板功能
    iphone webapp如何隐藏地址栏
    制作自己博客的分享按钮
    css3动画事件—webkitAnimationEnd
    获取随机的颜色
    制作自己博客的翻译工具
    兼容IE getElementsByClassName取标签
  • 原文地址:https://www.cnblogs.com/slider/p/2286950.html
Copyright © 2011-2022 走看看