Android Custom view with custom properties

Source: Internet
Author: User

This is the content in the Android UI fundamentals

Create a custom view

Creating a custom UI component first inherits a view class.
Start by creating a simple custom view that shows a cross line.

The first thing to do is to create a Crossview class that inherits from view.

    publicCrossView(Context context, AttributeSet attrs) {        super(context, attrs);    }

The second parameter of the constructor is used to pass the XML parameter, which is discussed later. Next we will rewrite the two basic methods: onMeasure and onDraw .

Onmeasure

The system invokes the onMeasure method to determine the dimensions of the view and its child views. Its two parameters are of the type int , but the two parameters are not ordinary numbers, but two MeasureSpec , MeasureSpec is a pattern and an integral size value of the combination, as an integer to achieve. There are several scenarios where the pattern value is:

Mode explain
UNSPECIFIED The parent view does not have any restrictions on this view, it can be any size
At_most The view can be any size less than or equal to the MeasureSpec medium size
Exactly Parent view requires that the view must be MeasureSpec of the specified size

When you create a custom view and override the onMeasure method, you must handle each case correctly, get the appropriate dimensions, and then you must call the method in, the onMeasure setMeasureDimensions parameter is the size you decide, and throws an exception if you do not call.
The following is the overridden onMeasure method code.

    @Override    protectedvoidonMeasure(intint heightMeasureSpec) {        setMeasuredDimension(calculateMeasure(widthMeasureSpec), calculateMeasure(heightMeasureSpec));    }

Note that the calculateMeasure methods are defined by ourselves, so let's do this.
Let's first define a default size of 100, which is DP ( I'm not sure ifit's DP).

privatestaticfinalint100;

Multiply the pixel density of the device to get the desired pixel value for the actual display.

int result = (int) (DEFAULT_SIZE * getResources().getDisplayMetrics().density);

Then we need to get the pattern and size from the Measurespec.

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

The next step specMode is to determine result what the value should be.

    • MeasureSpec.UNSPECIFIED
      Now that the parent control has no requirement for the size of the custom view, I will result in the default size, which means
int result = (int) (DEFAULT_SIZE * getResources().getDisplayMetrics().density);
    • MeasureSpec.AT_MOST
      At this point, the parent control does not think it can exceed the specified size value at this point, so we select the smallest of the specified value and the default value, which is legal in either case.
result = Math.min(specSize, result);
    • MeasureSpec.EXACTLY
      At this point the parent control requires that the child view must be a given dimension, so we let result it be equal to it.
result = specSize;

To synthesize the above discussion, finally our method code is as follows:

    Private Static Final intDefault_size = -;Private int calculatemeasure(intMEASURESPEC) {intresult = (int) (Default_size * getresources (). Getdisplaymetrics (). density);intSpecmode = Measurespec.getmode (Measurespec);intSpecsize = Measurespec.getsize (Measurespec);if(Specmode = = measurespec.exactly)        {result = Specsize; }Else if(Specmode = = measurespec.at_most)        {result = Math.min (specsize, result); }returnResult }
OnDraw

The method is called when the view should draw its contents. onDraw before we rewrite it, we'll first create an Paint object that handles things like color and text size.
CrossViewto create an object by using the constructor Paint

    private Paint mPaint;    publicCrossView(Context context, AttributeSet attrs) {        super(context, attrs);        new Paint();        mPaint.setAntiAlias(true);        mPaint.setColor(0xffff0000);    }

The above code creates a new Paint object and sets anti-aliasing and color.
Next rewrite the onDraw method, the template is as follows, canvas.save() and canvas.restore() I will not explain it without affecting the subsequent understanding.

    @Override    protectedvoidonDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.save();        // code goes here        canvas.restore();    }

We scaled the canvas based on the dimensions of the view so that we could use a floating-point number from 0 to 1 as the coordinates when we drew the line

    Private Static Final float[] mpoints = {0.5F0F0.5F1F0F0.5F1F0.5f};@Override    protected void OnDraw(Canvas canvas) {Super. OnDraw (canvas);        Canvas.save ();        Canvas.scale (GetWidth (), getheight ());        Canvas.drawlines (mpoints, mpaint);    Canvas.restore (); }

We add our own custom controls to the activity's XML

<LinearLayout xmlns:android="Http://schemas.android.com/apk/res/android"    Xmlns:tools="Http://schemas.android.com/tools"    Android:layout_width="Match_parent"    Android:layout_height="Match_parent"    android:orientation="Vertical"    Android:paddingleft="@dimen/activity_horizontal_margin"    Android:paddingright="@dimen/activity_horizontal_margin"    Android:paddingtop="@dimen/activity_vertical_margin"    Android:paddingbottom="@dimen/activity_vertical_margin"    Tools:context=". Mainactivity ">    <com.shaw.uitest.CrossViewandroid:layout_width="Wrap_content"  Android:layout_height="wrap_content" />                    <com.shaw.uitest.CrossViewandroid:layout_margintop="10DP"android:layout_ Width="Wrap_content"android:layout_height="wrap_content" />                        </linearlayout>

Run it and you can see the beginning of the article screen.

To add custom properties to a custom view

With a custom view, we want it to be configured with custom XML properties, to do this, you need to declare the property, then add a new namespace to the XML layout, and finally process the AttributeSet object that is passed to the custom view constructor.

declaring properties

In the res/values/directory, create a file with a attrs.xml (which can be a different name) and add the following to it:

<?xml version= "1.0" encoding= "Utf-8",  <resources ;  <declare-styleable  name  = "cross" ;  <attr  Span class= "Hljs-attribute" >name  = "Android:color" />  <attr  name  =  "rotation"  format  = "string" />  </declare-styleable ;  </resources ;   

declare-styleableelement has a name attribute, which is used to reference custom properties in code, each custom attribute is declared with an attr element that attr has name and format two properties, name for reference, format for its data type, If you use the default system properties, you do not need to define format, and if you try to define a different format for an existing property, the project cannot build. Declarations in the outer layer attr can be declare-styleable reused, just as with system properties, such as:

<?xml version= "1.0" encoding= "Utf-8"?><resources>    <attr name="Test" format="string" />    <declare-styleable name="foo">        <attr name="Test" />    </declare-styleable>    <declare-styleable name="Bar">        <attr name="Test" />    </declare-styleable></Resources>

You can also create custom values for attributes, such as

<attr name="enum_attr">    <enum name="value1" value="1" />    <enum name="value2" value="2" /></attr><attr name="flag_attr">    <flag Name="Flag1" value="0x01" />    <flag Name="Flag2" value="0x02" /></attr>

enumand flag all requirements are integers. The difference is that flag it can be used | to splice. For example android:gravity , the value is flag.

Using attributes in XML

To use the new properties in our XML, you must first declare the namespace for the view. In fact, we often see namespace's statement, such as we often see in the activity's XML file

xmlns:android="http://schemas.android.com/apk/res/android"

This namespace declares that all android attributes beginning with the keyword can be found in the Android package. To use a custom attribute, you need to declare a new namespace with the new package name, and add a new namespace for the Crossview property below. and add the relevant XML configuration to the custom view:

<LinearLayout xmlns:android="Http://schemas.android.com/apk/res/android"    Xmlns:tools="Http://schemas.android.com/tools"    Xmlns:crossview="Http://schemas.android.com/apk/res-auto"    Android:layout_width="Match_parent"    Android:layout_height="Match_parent"    android:orientation="Vertical"    Android:paddingleft="@dimen/activity_horizontal_margin"    Android:paddingright="@dimen/activity_horizontal_margin"    Android:paddingtop="@dimen/activity_vertical_margin"    Android:paddingbottom="@dimen/activity_vertical_margin"    Tools:context=". Mainactivity ">    <com.shaw.uitest.CrossViewandroid:layout_width="Wrap_content"android: Layout_height="Wrap_content"crossview:rotation="android:color" =  "#ff0000ff"/>                                    <com.shaw.uitest.CrossViewandroid:layout_margintop="10DP"android:layout_ Width="Wrap_content"android:layout_height="Wrap_content"crossview:rotation ="android:color" = "#ff00ff00"/>                                        </linearlayout>

The above declares that all crossview attributes that begin with (the name can be used in a different way) can be found in res. This is the wording of the Gradle request.

Using XML attributes in your code

CrossViewAn object is passed in the constructor AttributeSet that we can use to get the properties declared in the XML layout.
Update CrossView The constructor and add the corresponding function and member variables:

    Private floatmrotation; Public Crossview(context context, AttributeSet attrs) {Super(context, attrs); Mpaint =NewPaint (); Mpaint.setantialias (true); TypedArray arr = GetContext (). Obtainstyledattributes (Attrs, R.styleable.cross);intcolor = Arr.getcolor (R.styleable.cross_android_color, Color.Black);floatrotation = Arr.getfloat (r.styleable.cross_rotation,0f);        Arr.recycle ();        SetColor (color);    Setrotation (rotation); } Public void SetColor(intColor) {Mpaint.setcolor (color); } Public void setrotation(floatdegree) {mrotation = degree; }

Updated code at the same time onDraw

    @Override    protectedvoidonDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.save();        canvas.scale(getWidth(), getHeight());        0.50.5f);        canvas.drawLines(mPoints, mPaint);        canvas.restore();    }

Our center of rotation is the center of the canvas, not the upper-left corner.
Now run this program, as follows:

Android Custom view with custom properties

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.