Android Check Gaps (view)-The basic process for customizing view

Source: Internet
Author: User

View is a very important part of Android, commonly used view has button, TextView, EditView, ListView, GridView, various layout and so on, By combining these view combinations to create a rich and colorful interface, the experience of interface interaction in an application is often critical to the popularity of the application, so developers will find ways to make a more elegant interface, for example by customizing the view, In-depth study of the principle of view in order to better optimize its operation more smoothly and so on, and because of this, in the interview also often as the interviewer to focus on one of the subjects.

View is the base class for all controls, including button, TextView, EditView, and so on, directly or indirectly inherited from View,view and ViewGroup subclasses, namely LinearLayout, Relativelayout and so all belong to ViewGroup.

What we need to know is that on Android, either view or other interface, the right direction represents the positive direction of the x axis, and the lower direction represents the positive direction of the Y axis.

The basics of how View works

In Activitythread, when activity is created, the Decorview is added to the Window, the Viewrootimpl object is created, and Viewrootimpl and Decorview are associated, and Decorvie W is a top view of the Activity, in a default theme, it is divided into the title bar, and the content area, we added the view is added to the Decorview content area, the added view of the workflow is formally completed through Viewrootimpl Of

Viewroot, Decorview and View of the three major processes:

    • Viewroot: corresponding to Viewrootimpl, link WindowManager and Decorview, the three major processes of View are done through it. (The view's drawing process starts with the Viewroot performtraversals () method, which, through measure, layout, draw three processes, will finally be able to draw a view completely. )

    • Decorview: When creating a new Android app we all know that the default theme of the app's interface is divided into two parts: the title bar, the content area. And the top View of this interface is Decorview.

    • View is drawn through the measure, layout, draw three processes:
    1. Measure: Corresponds to the Onmeasure () method to measure the width and height of the view.
    2. Layout: Corresponds to the OnLayout () method, which determines the four vertices of a view, that is, the position of the view in the parent container.
    3. Draw: Corresponds to OnDraw (), drawing view. It is also in the OnDraw () method that we are able to draw the view we want on the canvas canvas in a custom view.
Custom View

More than one way to customize the view, you can directly inherit the view, overriding the OnDraw () method, you can also inherit the ViewGroup, you can inherit the existing controls (such as: TextView, linearlayout), etc., this article mainly introduces the direct inheritance view The way.

This way of directly inheriting view to implement a custom view is more flexible and can achieve many complex effects, the most important step is to rewrite the OnDraw () method, with the paint brush and other tools on the canvas canvas to do a variety of patterns to achieve the effect we want.

In fact, in the custom view process, the difficulty is often not how to use the brush itself, but to draw the idea of the expected effect, for example: you want to customize the view to make a line chart control, passing a set of data how to determine the corresponding point of the data on the canvas relative coordinates, The coordinates of the definite point need to be calculated by the relevant mathematical formula, and the correct formula is often the key to solve the problem.

This is the way to write a small round demo to illustrate the process of customizing the View.

    • Create a new class that inherits the View, add a construction method, set the paint brush, override the OnDraw () method, and first on the canvas, in the simplest way, a circle with a radius of 100.
/** * Custom View Simple example * Created by Liuwei on 17/12/14.    */public class MyView extends View {private final static String TAG = MyView.class.getSimpleName ();    Private Paint Mpaint = new paint ();    private int mcolor = Color.parsecolor ("#ff0000");        Public MyView (Context context) {super (context);        LOG.I (TAG, "MyView (Context context): Content=" + context);    Init ();        } public MyView (context context, @Nullable AttributeSet attrs) {Super (context, attrs); LOG.I (TAG, "MyView (context context, @Nullable AttributeSet attrs): content=" + Context + "|        attrs= "+ attrs);    Init (); private void Init () {Mpaint.setantialias (true);//anti-aliasing Mpaint.setcolor (mcolor);//Set color for brush} @O Verride protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (widthmeasurespec        , Heightmeasurespec); Override this method to set the default width, height int widthspecmode = measurespec.getmode (WIDTHMEASURESPE) for custom controls in wrap_content casesc);        int widthspecsize = measurespec.getsize (Widthmeasurespec);        int heightspecmode = Measurespec.getmode (Heightmeasurespec);        int heithtspecsize = measurespec.getsize (Heightmeasurespec); if (Widthspecmode = = Measurespec.at_most && Heightspecmode = = measurespec.at_most) {Setmeasureddimensi        On (200, 200);        } else if (Widthspecmode = = measurespec.at_most) {setmeasureddimension (heithtspecsize);        } else if (Heightspecmode = = measurespec.at_most) {setmeasureddimension (widthspecsize, 200);        }} @Override protected void OnDraw (canvas canvas) {LOG.I (TAG, "OnDraw:");        Super.ondraw (canvas);    Canvas.drawcircle (+, +, mpaint); }}

The running result is a red solid circle, in this example, in order to make the layout file wrap_content normal effect, rewrite the Onmeasure () method, on this issue, in this blog "Android Check Trap--Custom View" Wrap_ Content Invalid solution is also introduced, here is not much to say.

    • Extend the circle above: make the largest circle by making the center of the available area of the canvas a dot. Set padding for the custom View at the same time
      For a control, margin and padding,margin are outside the bounds of the control and do not require special handling of the margin when customizing the View. But the padding is different, is the internal spacing, we need to do in the inside of the control to let the layout file in the control set padding take effect.
private int mpaddingtop;private int mpaddingbottom;private int mpaddingleft;private int mpaddingright;private int Musablewidth; Available width (minus padding width) private int musableheight;//available height (minus padding height) private int musablestartx = 0; The x-coordinate of the start point of the brush private int musablestarty = 0; The brush actually points the Y coordinate of the private int mcirclex; center x coordinate private int mcircley;    Center y coordinate private int mcircleradius;//circle radius @overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas);    Mpaddingtop = Getpaddingtop ();    Mpaddingbottom = Getpaddingbottom ();    Mpaddingleft = Getpaddingleft ();    Mpaddingright = Getpaddingright ();    Available widths and widths to consider padding musablewidth = getwidth ()-mpaddingright-mpaddingleft;    Musableheight = GetHeight ()-mpaddingtop-mpaddingbottom;    Brush starting point to consider padding musablestartx = mpaddingleft;    Musablestarty = Mpaddingtop;    Determine the center of the available zone for the Centre Mcirclex = musablestartx + musablewidth/2;    Mcircley = Musablestarty + musableheight/2; Determines the radius of the circle, in the shorter half of the available width and height, as the radius if (musablewidTh <= musableheight) {Mcircleradius = MUSABLEWIDTH/2;    } else {Mcircleradius = MUSABLEHEIGHT/2; } canvas.drawcircle (Mcirclex, Mcircley, Mcircleradius, mpaint);}

Set Paddingleft to 15dp,paddingright in the layout file to 30DP, in order to better see the spacing, set the control's background color to black to see the effect:

<cn.codingblock.view.reset_view.MyView        android:id="@+id/myview"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_margin="10dp"        android:paddingLeft="15dp"        android:paddingRight="30dp"        android:background="#000"/>


As can be seen, after the OnDraw () method has been processed for padding, the center of the circle is guaranteed to be centered in the available area, regardless of how the padding is set in the layout file.

    • Add custom properties to a custom View

First create an XML file under the Res/values path and add a property that sets the color of the circle:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyView">        <attr name="circle_color" format="color"/>    </declare-styleable></resources>

Resolving properties in a construction method

public MyView(Context context, @Nullable AttributeSet attrs) {    super(context, attrs);    TypedArray typeArray = context.obtainStyledAttributes(attrs, R.styleable.MyView);    mColor = typeArray.getColor(R.styleable.MyView_circle_color, mColor);    typeArray.recycle();    init();}

Finally in the layout file this is the property, it is important to note that when using the custom properties to add xmlns:app= "Http://schemas.android.com/apk/res-auto" can be.

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="cn.codingblock.view.activity.MyViewActivity">    <cn.codingblock.view.reset_view.MyView        android:id="@+id/myview"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_margin="10dp"        android:paddingLeft="15dp"        android:paddingRight="30dp"        app:circle_color="#ad42ce"        android:background="#000"/></LinearLayout>

Change the color after the following:

Add an interactive event Motionevent touch event for a custom view
@Overridepublic boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            Log.i(TAG, "onTouchEvent: ACTION_DOWN");            break;        case MotionEvent.ACTION_UP:            Log.i(TAG, "onTouchEvent: ACTION_UP");            break;        case MotionEvent.ACTION_MOVE:            Log.i(TAG, "onTouchEvent: ACTION_MOVE");            break;    }    return super.onTouchEvent(event);}

In custom View, override the Ontouchevent () method to get Motionevent, as written in the code above, motionevent more commonly used events are three Action_down, Action_move, action_up Each finger is pressed-move-away.

Next to the above circular demo add a small event, that is, every time the finger click on the screen, the circle randomly change a color:

private Random mRandom = new Random(100);private int[] mColors = new int[] {  Color.parseColor("#ff0000"),  Color.parseColor("#ffffff"),  Color.parseColor("#ff00ff"),  Color.parseColor("#ffff00"),  Color.parseColor("#ff00ff"),  Color.parseColor("#0000ff")};@Overridepublic boolean onTouchEvent(MotionEvent event) {    switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            mColor = mColors[mRandom.nextInt(6)];            mPaint.setColor(mColor);            invalidate(); // 通知控件重绘            break;        case MotionEvent.ACTION_UP:            Log.i(TAG, "onTouchEvent: ACTION_UP");            break;        case MotionEvent.ACTION_MOVE:            Log.i(TAG, "onTouchEvent: ACTION_MOVE");            break;    }    return super.onTouchEvent(event);}

The effect is as follows:

You can also expand on this basis slightly, for example: through the Event.getx () and event.gety () to get the coordinates of the touch point, to determine whether the point falls in the circular area, so that only the point finger to the circle area to change the color, otherwise does not change. Interested children's shoes can try it yourself.

The invalidate () method is used in the above code to notify the view redraw, but in fact postinvalidate () can also notify the view redraw, so what is the difference between the two?

In a nutshell, invalidate () can only be used in the UI thread, and postinvalidate () may be used in child threads.

Scalegesturedetector pinch-to-go finger detection

In addition to the most common motionevent events above, Android also provides a lot of interesting events, like gesturedetector (gesture detection), Velocitytracker (speed tracking) and so on, it is very convenient to use, in fact, as long as you want to, These events can also be implemented in the Ontouchevent () method, and then add a zoom function for the above round Demo, that is, using the Scalegesturedetector implementation, the effect with the usual on the phone when viewing photos we use two fingers to enlarge/ Shrink the picture as well.

Scalegesturedetector is also very simple to use, first you need to initialize and add a retraction gesture listener, and in the Ontouchevent () method, through the Scalegesturedetector.ontouchevent (event) to let Scalegesturedetector take over the touch event, note the rest of the notes in the code.

Add the following code based on the above code:

Private Context mcontext;private Scalegesturedetector mscalegesturedetector; Zoom gesture Detection Private float mscalerate = 1; Zoom ratio private void init () {Mpaint.setantialias (true);//anti-aliasing Mpaint.setcolor (mcolor);//Set color//initialization for brushes Scaleg Esturedetector and add a zoom gesture listener Mscalegesturedetector = new Scalegesturedetector (Mcontext, Monscalegesturelistener);}    @Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas);    Mpaddingtop = Getpaddingtop ();    Mpaddingbottom = Getpaddingbottom ();    Mpaddingleft = Getpaddingleft ();    Mpaddingright = Getpaddingright ();    Available widths and widths to consider padding musablewidth = getwidth ()-mpaddingright-mpaddingleft;    Musableheight = GetHeight ()-mpaddingtop-mpaddingbottom;    Brush starting point to consider padding musablestartx = mpaddingleft;    Musablestarty = Mpaddingtop;    Determine the center of the available zone for the Centre Mcirclex = musablestartx + musablewidth/2;    Mcircley = Musablestarty + musableheight/2; Determines the radius of the circle, with a shorter half of the available width and height for the circle radius if (musablewidth <= musableheight) {        Mcircleradius = MUSABLEWIDTH/2;    } else {Mcircleradius = MUSABLEHEIGHT/2;    }//Let radius multiplied by magnification Mcircleradius *= mscalerate; Canvas.drawcircle (Mcirclex, Mcircley, Mcircleradius, mpaint);} @Overridepublic boolean ontouchevent (Motionevent event) {switch (event.getaction ()) {case Motionevent.action_d            Own:mcolor = Mcolors[mrandom.nextint (6)];            Mpaint.setcolor (Mcolor); Invalidate ();        Notifies the control to redraw the break;            Case MOTIONEVENT.ACTION_UP:LOG.I (TAG, "ontouchevent:action_up");        Break            Case MOTIONEVENT.ACTION_MOVE:LOG.I (TAG, "ontouchevent:action_move");    Break    }//Let the zoom gesture detector take over the touch event if (Mscalegesturedetector.ontouchevent (event)) {return true; } return Super.ontouchevent (event);} Private Scalegesturedetector.onscalegesturelistener Monscalegesturelistener = new Scalegesturedetector.onscalegesturelistener () {@Override public boolean onscale (ScAlegesturedetector detector) {log.i (TAG, "Onscale:" + detector.getscalefactor ());        Get the scaling factor and multiply the magnification to mscalerate *= detector.getscalefactor ();        Postinvalidate ();    return true; } @Override public Boolean onscalebegin (Scalegesturedetector detector) {log.i (TAG, "Onscalebegin:" + Detect        Or.getscalefactor ());    return true; } @Override public void Onscaleend (Scalegesturedetector detector) {log.i (TAG, "onscaleend:" + detector.gets    Calefactor ()); }};

The above code needs to be aware that the scaling gesture does not work correctly after Scalegesturedetector captures the event to properly consume the event (note where true is returned in the code).

Custom view has always been a very important part of Android, in peacetime development want to make a personality cool interactive interface is inseparable from the custom view, custom view said difficult not difficult, said simple is not simple, in short, a beginning, a single, as long as we have a good grasp of custom view Basic knowledge, and then the complex interface can be completed step-by-step.

Finally want to say is, this series for Bo master on Android knowledge again comb, check the learning process, on the one hand is forgetting things to review again, on the other hand believe in the process of re-learning will have a huge new harvest, if you also have with me the same idea, may wish to pay attention to my study together , explore each other and make progress together!

Reference documents:

    • Explore the art of Android development
    • "Android Development advanced from small to expert"

Android Check Gaps (view)-The basic process for customizing view

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.