Android custom components (2) How to Implement custom components

Source: Internet
Author: User

Android custom components (2) How to Implement custom components

 

Introduction

Android provides a powerful component model for building the UI. Two base classes: View and ViewGroup.

The list of available widgets includes buttons, TextView, EditText, ListView, CheckBox, RadioButton, Gallery, and Spinner, as well as some useful components: AutoCompleteTextView, ImageSwitcher, and TextSwitcher.

Available layout S: LinearLayout, FrameLayout, RelativeLayout, AbsoluteLayout, GridLayout (later on api level 14 or v7-support)


Basic practices

1. inherit from the subclass of View or View

2. rewrite some methods of the parent class, such as onDraw (), onMeasure (), and onLayout ().

3. Use custom component classes.


Fully custom components

1. The most common practice is to inherit from the View to implement your custom components.

2. Provides a constructor that uses property parameters or custom attributes.

3. You may want to create your own event listener, attribute accessors, modifiers, or other actions in the component.

4. Almost certainly rewrite onDraw () and onMeasure (). By default, onDraw () is useless, and onMeasure () is used to set a size of X.

5. Rewrite other methods as needed...

 

OnDraw () and onMeasure ()

OnDraw () provides a Canvas that can draw 2D images.

To draw 3D images, inherit GLSurfaceView. For more information, see GLSurfaceViewActivity in api-demo.

 

OnMeasure () Measurement Component

1. Call this method when measuring the width and height.

2. The measurement and calculation component should be carried out to display the width and height. It should be kept within the input specification range as far as possible, although it can choose to exceed them (in this case, the parent view can choose what to do, including cropping, scrolling, and throwing an exception, or require onMeasure () to try again, or use different measurement specifications)

3. After calculating the width and height, you must call setMeasuredDimession (int width, int height) to set it. Otherwise, an exception is thrown.

 

The following is a summary of some methods that can be called in the View (not all of them are included. You can View methods similar to onXxx on your own ):

 

Category Methods Description
Creation Constructors There is a form of the constructor that are called when the view is created from code and a form that is called when the view is inflated from a layout file. the second form shoshould parse and apply any attributes defined in the layout file.
onFinishInflate() Called after a view and all of its children has been inflated from XML.
Layout onMeasure(int, int) Called to determine the size requirements for this view and all of its children.
onLayout(boolean, int, int, int, int) Called when this view shoshould assign a size and position to all of its children.
onSizeChanged(int, int, int, int) Called when the size of this view has changed.
Drawing onDraw(Canvas) Called when the view shocould render its content.
Event processing onKeyDown(int, KeyEvent) Called when a new key event occurs.
onKeyUp(int, KeyEvent) Called when a key up event occurs.
onTrackballEvent(MotionEvent) Called when a trackball motion event occurs.
onTouchEvent(MotionEvent) Called when a touch screen motion event occurs.
Focus onFocusChanged(boolean, int, Rect) Called when the view gains or loses focus.
onWindowFocusChanged(boolean) Called when the window containing the view gains or loses focus.
Attaching onAttachedToWindow() Called when the view is attached to a window.
onDetachedFromWindow() Called when the view is detached from its window.
onWindowVisibilityChanged(int) Called when the visibility of the window containing the view has changed.

 

 

Custom View Example

Examples in adi-demo: LabelView

 

/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.view.View;/** * 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 {    /**     * Constructor.  This version is only needed if you will be instantiating     * the object manually (not from a layout XML file).     * @param context the application environment     */    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();        Resources.StyledAttributes a = context.obtainStyledAttributes(attrs,                R.styleable.LabelView);        CharSequence s = a.getString(R.styleable.LabelView_text);        if (s != null) {            setText(s.toString());        }        ColorStateList textColor = a.getColorList(R.styleable.                                                  LabelView_textColor);        if (textColor != null) {            setTextColor(textColor.getDefaultColor(0));        }        int textSize = a.getInt(R.styleable.LabelView_textSize, 0);        if (textSize > 0) {            setTextSize(textSize);        }        a.recycle();    }     */    private void initLabelView() {        mTextPaint = new Paint();        mTextPaint.setAntiAlias(true);        mTextPaint.setTextSize(16);        mTextPaint.setColor(0xFF000000);        mPaddingLeft = 3;        mPaddingTop = 3;        mPaddingRight = 3;        mPaddingBottom = 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;        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) + mPaddingLeft                    + mPaddingRight;            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;        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()) + mPaddingTop                    + mPaddingBottom;            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, mPaddingLeft, mPaddingTop - mAscent, mTextPaint);    }    private Paint mTextPaint;    private String mText;    private int mAscent;}

 

Apply the layout xml of the custom component:

 

         
          
           
    
   
  
 

 

This example demonstrates:

1. inherit full custom components of the custom View

2. constructor with parameters (some attribute parameters are set in xml ). The custom property R. styleable. LabelView is also used.

3. Some standard public methods, such as setText (), setTextSize (), setTextColor ()

4. onMeasure () measurement component size, measured internally by measureWidth (int measureSpec) and measureHeight (int measureSpec.

5. onDraw () draws the Label on the Canvas.

 

A composite component is composed of some existing components into a new one. To create a composite component: 1. You usually need to create a class that inherits from a Layout or ViewGroup. 2. In constructor, you must first call the corresponding constructor of the parent class. Then set some required components for composite. You can use custom attributes. 3. you can create a listener to listen for some possible actions. 4. there may be some properties of the get/set Method 5. if you inherit from a Layout class, you do not need to override onDraw () and onMeasure () because the Layout class has default behavior. If necessary, you can also rewrite it. 6. You may rewrite some other onXxx () to achieve the desired effect.

Composite component example api-the internal class SpeachView in List4 and List6 in demo. The following is the source code in List6.
Private class SpeechView extends LinearLayout {public SpeechView (Context context, String title, String dialogue, boolean expanded) {super (context); this. setOrientation (VERTICAL); // Here we build the child views in code. they cocould also have // been specified in an XML file. mTitle = new TextView (context); mTitle. setText (title); addView (mTitle, new LinearLayout. layoutParams (LayoutParams. MATCH_PAR ENT, LayoutParams. WRAP_CONTENT); mDialogue = new TextView (context); mDialogue. setText (dialogue); addView (mDialogue, new LinearLayout. layoutParams (LayoutParams. MATCH_PARENT, LayoutParams. WRAP_CONTENT); mDialogue. setVisibility (expanded? VISIBLE: GONE);}/*** Convenience method to set the title of a SpeechView */public void setTitle (String title) {mTitle. setText (title);}/*** Convenience method to set the dialogue of a SpeechView */public void setDialogue (String words) {mDialogue. setText (words);}/*** Convenience method to expand or hide the dialogue */public void setExpanded (boolean expanded) {// This method does not have mDialogue in List4. SetVisibility (expanded? VISIBLE: GONE);} private TextView mTitle; private TextView mDialogue ;}
SpeachView, inherited from LinearLayout, vertical layout. There is a TextView title and a TextView dialogue. List4 completely expands two textviews; List6 click the title to contract/expand dialogue.
Modify the existing View type to inherit from an existing View to enhance its function and meet the needs.
The sdk contains a NotePad example project. One of the classes is the extended EditText. In the NoteEditor class:
Public static class LinedEditText extends EditText {private Rect mRect; private Paint mPaint; // This constructor is used by LayoutInflater public LinedEditText (Context context, AttributeSet attrs) {super (context, attrs ); // Creates a Rect and a Paint object, and sets the style and color of the Paint object. mRect = new Rect (); mPaint = new Paint (); mPaint. setStyle (Paint. style. STROKE); mPaint. setColor (0x800000FF);}/*** This is called to draw the LinedEditText object * @ param canvas The canvas on which the background is drawn. * // @ Override protected void onDraw (Canvas canvas) {// Gets the number of lines of text in the View. int count = getLineCount (); // There are several lines in edittext. edittext inherits textview // Gets the global Rect and Paint objects Rect r = mRect; Paint paint = mPaint; /** Draws one line in the rectangle for every line of text in the EditText */for (int I = 0; I <count; I ++) {// Gets the baseline coordinates for the current line of text int baseline = getLineBounds (I, r); // assign the range coordinates of a row to the rectangle r; returns the baseline coordinate of a line y/** Draws a line in the background from the left of the rectangle to the right, * at a vertical position one dip below the baseline, using the paint object * for details. */canvas. drawLine (r. left, baseline + 1, r. right, baseline + 1, paint); // draw a line with the width of the original line, height: + 1 pixel from baseline} // Finishes up by calling the parent method super. onDraw (canvas );}}

Defines a public static internal class so that it can be accessed: NoteEditor. myEditText is a static internal class, meaning that it does not rely on external class members and does not generate some "combination methods ".
Inherited from the initialization constructor of the EditText class, the constructor of the parent class is called first, and it is a constructor with attribute parameters. Inflate is an xml layout file. Only onDraw () is overwritten. A blue line is drawn in onDraw (), which starts from the baseline of each line of text and is 1 pixel down. The width is the row width. Before the method ends, call super. onDraw () to use the custom component.
 

Use a fully qualified class name to introduce custom components. Use $ to reference internal classes.


Android custom components (I) basic implementation and custom properties: http://blog.csdn.net/jjwwmlp456/article/details/38728519


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.