A preliminary summary of custom view in Android

Source: Internet
Author: User
Tags getcolor

Overview

During the development process, it is often encountered that the controls provided in the system do not meet the design requirements of the product, and it may be necessary to consider using a custom view to implement the design details of the product. There are two types of custom view, one is a custom control (inherited view), the other is a custom layout container (inherited ViewGroup), and the following is a simple summary of the application for custom control view.

Custom View

When customizing view, most of us only need to rewrite two methods onmeasure (), OnDraw (). Onmeasure () is responsible for measuring the current view size, and OnDraw () is responsible for drawing the current view. In addition to customizing the view, you also need to write a construction method with the AttributeSet parameter.

Defining Construction methods
    publicCustView(Context context) {        super(context);    }    publicCustView(Context context, AttributeSet attrs) {        super(context, attrs);    }

The above two different construction methods indicate that there are two different ways to create the view. If you create custview directly in the form of code, the first constructor method is called. Such as:

new CustView(this);

If you create this view object from an XML layout file, the system automatically calls the second construction method. The method cannot be omitted because the system obtains the properties of the view setting in the XML layout file from this method. Otherwise, the system throws an exception. For this method, Google docs describes this:
Public View (context context, AttributeSet attrs)

Constructor that was called when inflating a view from XML. This was called when a view was being constructed from an XML file, supplying attributes that were specified in the XML file . This version uses a default style of 0, so the attribute values applied is those in the Context ' s Theme and the Give N AttributeSet.
The idea is that when you populate a view from an XML layout, the constructor is called. Called when view is being created from an XML layout and provides the properties specified in the XML file.
So the property that sets the view in the XML layout is passed in by this method.

Overriding the Onmeasure () method

The

above-mentioned Onmeasure () method is used to measure the width and height of the view. In the XML layout file, we can use Wrap_content or match_parent for attributes Layout_width and layout_height without writing specific dimensions. These two parameters mean "wrap content" and "match all the space that the parent layout gives us." By default, the system is processed against the property values above. We can set the size we want by rewriting onmeasure (). The method prototype is as follows:
protected void onmeasure (int widthmeasurespec, int heightmeasurespec)

This method contains two parameters Widthmeasurespec and Heightmeasurespec. These two parameters represent the features applied by the parent container on the horizontal space and the elements imposed by the parent container on the vertical space. The popular point is that they contain a wide-height size and measurement mode.
We all know that when setting the width height there can be three choices, a specific value, match_parent, and Wrap_content. There are also three types of measurement modes: Unspecified,exactly,at_most. We can use the Measurespec class to obtain the corresponding size and measurement mode of the above parameters. Like what:
int widthsize = measurespec.getsize (Widthmeasurespec);
int widthmode = Measurespec.getmode (Widthmeasurespec);
These three measurement modes represent the meaning of each:
UNSPECIFIED: The parent container does not impose any restrictions on the current view, and the current view can display any size.
Exactly: The parent container determines the specific size of the current view, and the view is limited to that dimension. The current size is the size of the view that should be set.
At_most: The current size is the maximum size the view can achieve.
The relationship between the above three measurement modes and the values we set for the width and height properties is as follows:
Match_parent corresponds to exactly: Because match_parent represents the size of the parent control, and the size of the parent view is fixed, the view size is also determined, so the measurement mode is exactly.
Wrap_content corresponds to At_most:wrap_content, which is the size of the contents of the package view, with the parent view as the reference size, no more than the size of the parent view.
The fixed size (100DP) corresponds to the exactly: the user specifies a size that is consistent with the match_parent nature.
Below we rewrite the Onmeasure method to implement the view's width height as a square. The default width height is 100px, you can set a different size value (greater than the default value)

    @Override    protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec);intwidth = GetSize ( -, Widthmeasurespec);intHeight = GetSize ( -, Heightmeasurespec);if(Width > height)        {width = height; }Else{height = width; } setmeasureddimension (width, height);//To store the newly calculated width and height measurements, otherwise it will not take effect}Private int GetSize(intDefaultSize,intMEASURESPEC) {intMysize = defaultsize;intSize = Measurespec.getsize (MEASURESPEC);intmode = Measurespec.getmode (MEASURESPEC);Switch(mode) { CaseMeasurespec.unspecified://No size specified, set default size.Mysize = defaultsize; Break; Casemeasurespec.exactly://If the value set in the layout is greater than the default value, the values set in the layout are used, corresponding to the match_parent and fixed values            if(Size > DefaultSize)            {mysize = size; } Break; CaseMeasurespec.at_most://If the value in the measurement mode is greater than the default, take the default value, corresponding to the wrap_content            if(Size > DefaultSize)            {mysize = defaultsize; } Break; }returnMysize; }

Layout File Settings:

<?xml version= "1.0" encoding= "Utf-8"?><linearlayout xmlns:android="Http://schemas.android.com/apk/res/android"  Android:id="@+id/view_pager_box"android:layout_width="Match_parent"  Android:layout_height="Match_parent"android:orientation="Horizontal" >                    <com.yuminfeng.myviewpager.CustViewandroid:id="@+id/custview"android: Layout_width="Match_parent"android:layout_height="100DP"android:background ="@android: Color/holo_red_dark" />                                </linearlayout>

Run as follows:

If you log off the Onmeasure method, the following:

Rewrite OnDraw ()

The OnDraw method is used to draw the graphic effect that the user wants. Below we have implemented the drawing of a hollow circle on the view, as follows:

    @Override    protectedvoidonDraw(Canvas canvas) {        super.onDraw(canvas);        int r = getMeasuredWidth()/2;    //使用getMeasuredWidth 可以获得在onMeasure方法中新计算的宽度        int cx = getLeft() + r;            //getLeft 表示的是当前View的左边到屏幕左边框的位置距离。这里不建议使用,因为如果view在左边使用其他View时,会影响该值。        canvas.drawCircle(r, r, r-20//该方法中的四个参数,前两个表示圆心的x,y的坐标。这两个值表示的是相对于该View中的位置,与其他view的位置无关。    }

It also involves a paint class that only needs to be initialized in the constructor method:

privatevoidinitPaint() {        new Paint();        mPaint.setAntiAlias(true//设置抗锯齿的效果        //设置画笔样式为描边        mPaint.setStrokeWidth(3);  //设置笔刷的粗细度        //设置画笔的颜色    }

The execution effect of the above code,

Adding custom properties

We add custom properties to Custom view, which makes it easy for users to use the view to cope with different scenarios. Makes the custom view more extensible.
First, we need to create a new file named Attrs.xml in the/res/values directory.

<?xml version= "1.0" encoding= "Utf-8"?><resources>    <!--name as a property, it can be taken casually, but it is recommended to use the name of view-- -    <declare-styleable name="Custview">        <!--Declare our properties, note that the value of format is not random ---        <attr name="Paintcolor" format="Color" />        <attr name="paintsize" format="Dimension" />     </declare-styleable></Resources>

The name of each property has a corresponding format value in the file that defines the attribute, and each format value represents a different meaning, with a few values:

After the Attrs.xml file is created, then we apply the properties in the Attrs.xml to the layout file

<?xml version= "1.0" encoding= "Utf-8"?><linearlayout  xmlns: Android  = "http://schemas.android.com/apk/res/android"  xmlns:custview  =" http://schemas.android.com/apk/res/ Com.yuminfeng.myviewpager " android:layout_width  =     "match_parent"  android:layout_height  = "match_parent"  android:orientation  = "horizontal" ;     <com.yuminfeng.myviewpager.CustViewandroid:id="@+id/custview"android: Layout_width="Match_parent"android:layout_height="100DP"Custview: Paintcolor="@android: Color/holo_orange_dark"custview:paintsize="10DP" />                                         </linearlayout>

Note When you use a custom property in a layout file, you must set the namespace. The name of the named control can be arbitrarily taken, such as: Custview. However, the value of the namespace is made up of a fixed prefix "http://schemas.android.com/apk/res/" + "package name". Once the namespaces are set up, we can add custom properties to the control properties, such as: Custview:paintcolor and Custview:paintsize.

Finally, we call the custom attribute in the code as follows:

private void Initattrs (ContextContextAttributeSetATTRS) {//Through this method, you can remove the attrs in theCustviewProperty.Custviewis the name of the tag we declare-styleable in the Attrs.xml file.TypedArray  Type = Context.obtainstyledattributes(attrs, R.  Styleable. Custview);Remove each label property by naming it as follows:R. Styleable + Property Collection name + Underscore + property name, if not, use default value Paintcolor = type. GetColor(R.  Styleable. custview_paintcolor, Color. BLACK);paintsize = (int) type. Getdimension(R.  Styleable. custview_paintsize, 3);Finally, you need toTypedArrayObject Recycling type. Recycle();}

The complete code is as follows:

 PackageCom.yuminfeng.myviewpager;ImportAndroid.content.Context;ImportAndroid.content.res.TypedArray;ImportAndroid.graphics.Canvas;ImportAndroid.graphics.Color;ImportAndroid.graphics.Paint;ImportAndroid.util.AttributeSet;ImportAndroid.view.View; Public  class custview extends View {    PrivatePaint Mpaint;Private intPaintcolor;Private intPaintsize; Public Custview(Context context) {Super(context); Initpaint ();//Initialize brush} Public Custview(context context, AttributeSet attrs) {Super(context, attrs); Initattrs (Context,attrs);//Initialize property valuesInitpaint ();//Initialize brush}Private void Initattrs(Context context,attributeset attrs) {//Through this method, you can remove the Custview attribute from the attrs. Custview is the name of the tag we declare-styleable in the Attrs.xml file. TypedArray type = Context.obtainstyledattributes (Attrs, R.styleable.custview);//Remove each label property, named by: R.styleable + attribute collection name + underscore + attribute name, if not, use default valuePaintcolor = Type.getcolor (R.styleable.custview_paintcolor, Color.Black); Paintsize = (int) Type.getdimension (R.styleable.custview_paintsize,3);///finally need to recycle Typedarray objectsType.recycle (); }Private void Initpaint() {Mpaint =NewPaint (); Mpaint.setantialias (true);//Set anti-aliasing effectsMpaint.setstyle (Paint.Style.STROKE);//Set brush style to strokeMpaint.setstrokewidth (paintsize);//Set the thickness of the brushMpaint.setcolor (Paintcolor);//Set the color of the brush}@Override    protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec);intwidth = GetSize ( -, Widthmeasurespec);intHeight = GetSize ( -, Heightmeasurespec);if(Width > height)        {width = height; }Else{height = width; } setmeasureddimension (width, height);//To store the newly calculated width and height measurements, otherwise it will not take effect}Private int GetSize(intDefaultSize,intMEASURESPEC) {intMysize = defaultsize;intSize = Measurespec.getsize (MEASURESPEC);intmode = Measurespec.getmode (MEASURESPEC);Switch(mode) { CaseMeasurespec.unspecified://No size specified, set default size.Mysize = defaultsize; Break; Casemeasurespec.exactly://If the value set in the layout is greater than the default value, the values set in the layout are used, corresponding to the match_parent and fixed values            if(Size > DefaultSize)            {mysize = size; } Break; CaseMeasurespec.at_most://If the value in the measurement mode is greater than the default, take the default value, corresponding to the wrap_content            if(Size > DefaultSize)            {mysize = defaultsize; } Break; }returnMysize; }@Override    protected void OnDraw(Canvas canvas) {Super. OnDraw (canvas);intR = getmeasuredwidth ()/2;//Use Getmeasuredwidth to get the new calculated width in the Onmeasure method        intCX = GetLeft () + R;//getleft represents the distance from the left side of the current view to the left border of the screen. This is not recommended because the value is affected if the view is using a different view on the left. Canvas.drawcircle (R, R, R -, Mpaint);//Four parameters in the method, the first two represent the coordinates of X, y of the center. These two values represent the position relative to the view, regardless of the location of the other view. }}

The execution effect of the above code,

This is the end of the custom view, and I'll continue with the custom viewgroup.

A preliminary summary of custom view in Android

Related Article

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.