Customizing View and Event handling

Source: Internet
Author: User

Look first.

Custom view can actually be fully integrated from view,viewgroup, or existing view.

    publicJumpCircleView(Context context) {        thisnull);//可以直接new    }    publicJumpCircleView(Context context, AttributeSet attrs) {        this0);//可以在xml文件中使用    }

The notes are clear.

There is also a constructor method, which is 3 parameters, and you can use a custom property

     publicJumpCircleViewint defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.JumpCircleView, defStyleAttr, R.style.AppTheme);        custom_size = a.getDimensionPixelSize(R.styleable.JumpCircleView_size, SIZE);        custom_background = a.getColor(R.styleable.JumpCircleView_background_color, DEFAULT_COLOR);        a.recycle();        init();    }

The third constructor is more than the second constructor of the value of an int, called defstyleattr, judging from the name, this is a parameter about the custom property, in fact, our guess is correct, the third constructor will not be called by the system default, but we need to explicitly call, For example, call the third function in the second constructor and set the third argument to 0.

Onmeasure–>onlayout–>ondraw
Specific implementation process

In Android, a view's drawing process includes: Measure,layout and draw, knowing the size of a view to occupy the interface by Onmeasure, and then onlayout know where the control should be located, Finally through the OnDraw method to draw this control, and then can be displayed in front of the user, I will analyze each of the three methods of the role.

    • Onmeasure measurement, by measuring the size of a view to be accounted for, the method parameter is a value of two int, we all know that in Java, the int is composed of 4 bytes (32bit), in Measurespce, with the first two to represent mode, Use the latter 30 digits to indicate size
 int  widthmode = Measurespec.getmode ( WIDTHMEASURESPEC); int  widthsize = measurespec.getsize (Widthmeasurespec); int  heightmode = Measurespec.getmode (Heightmeasurespec); int  heightsize = measurespec.getsize (Heightmeasurespec); int  measuredheight, measuredwidth; if  (Widthmode = = measurespec.exactly) {measuredwidth = widthsize; } else  {measuredwidth = SIZE; } if  (Heightmode = = measurespec.exactly) {measuredheight = Heightsize ; } else  {measuredheight = SIZE; } setmeasureddimension (Measuredwidth, measuredheight); 
MeasureSpce的mode有三种:EXACTLY, AT_MOST,UNSPECIFIED,除却UNSPECIFIED不谈,其他两种mode:当父布局是EXACTLY时,子控件确定大小或者match_parent,mode都是EXACTLY,子控件是wrap_content时,mode为AT_MOST;当父布局是AT_MOST时,子控件确定大小,mode为EXACTLY,子控件wrap_content或者match_parent时,mode为AT_MOST。所以在确定控件大小时,需要判断MeasureSpec的mode,不能直接用MeasureSpec的size。在进行一些逻辑处理以后,调用setMeasureDimension()方法,将测量得到的宽高传进去供layout使用。需要明白的一点是 ,测量所得的宽高不一定是最后展示的宽高,最后宽高确定是在onLayout方法里,layou(left,top,right,bottom),不过一般都是一样的。
    • OnLayout Actually, I did not rewrite the OnLayout method when I was customizing Sketchview, because Sketchview is simply a view, it is not a view container, no child view, And the OnLayout method is mainly specific placement of sub-view position, horizontal or vertical placement, so in a simple custom view is not required to rewrite the OnLayout method, but it is important to note that Whether or not the margin property of a child view is in effect depends on whether the parent is processing in its own OnLayout method, and the view Padding property is in effect in the OnDraw method.

    • OnDraw finally talked about the play, general custom control the most expensive thing is this method, need in this method, with paint on the canvas to draw the pattern you want, so a custom view is finished. Here's a detailed picture of how to draw the pattern you want on the canvas.

On the OnDraw method, in addition, if the view is directly inherited, then the way to rewrite OnDraw is to completely delete the Super.ondraw (canvas), because its default implementation is NULL. In fact, at any time should go to point into the super () method is empty implementation. For example, if you inherit from button, then the super () method of the OnDraw method cannot be deleted.

      @Override    protected void OnDraw(Canvas canvas) {//super () front is the effect you want to draw        if(mprogressenable) {Drawable drawable =NewColordrawable (Color.Blue);intleft =0;inttop =0;intright = (int) (Mprogress *1.0F/mmax * Getmeasuredwidth () +. 5f);intBottom = Getbottom (); Drawable.setbounds (left, top, right, bottom);//Required. Tell the scope of the drawingDrawable.draw (canvas); }Super. OnDraw (canvas);//Draw text, also draw background}
Get a square

In daily development, we occasionally need a square imageview, generally by specifying the width of the height, but when the height is uncertain, we can only hope that the Android OST support to define the scale of the view, but the reality is brutal, the system seems to have not provided similar properties, So we can only achieve by ourselves, in fact, their own writing is also very simple, only need to change a parameter on OK,

    @Override   protectedvoidonMeasure(intint heightMeasureSpec) {       super.onMeasure(widthMeasureSpec, widthMeasureSpec);   }

Not careful observation is not to see the mystery of it, although here to make a copy of the view of the onmeasure, but seemingly did not do any processing, directly call the Super method, but carefully observe the words will find that when the super method is called, the second parameter changed, Originally should be heightmeasurespec but replaced with Widthmeasurespec, so the view height is the width of the view, a squareview realized, even if through a custom attribute to achieve a custom scale view.

Custom properties
     <!--自定义view蹦跳-->    <declare-styleable name="JumpCircleView">        <attr name="background_color" format="color" />        <attr name="size" format="dimension" />    </declare-styleable>

Use

     <com.marc.chatpicture.widget.JumpCircleView                android:id="@+id/sketch_view"                app:size="24dp"                app:background_color="@color/colorPrimary"                android:layout_width="200dp"                android:layout_height="200dp"                android:layout_gravity="center" />

If you really want to use it, don't forget:

     publicJumpCircleViewint defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.JumpCircleView, defStyleAttr, R.style.AppTheme);        custom_size = a.getDimensionPixelSize(R.styleable.JumpCircleView_size, SIZE);        custom_background = a.getColor(R.styleable.JumpCircleView_background_color, DEFAULT_COLOR);        a.recycle();        init();    }

Here is a specific example:

     Public  class jumpcircleview extends View {    Private intCustom_size;Private intCustom_background;PrivatePaint Mpaint;Private intMheight;Private intMwidth;Private floatScale =1FPrivate Final intSIZE = the;//default size    Private Final intDefault_color = Color.Blue;//The color of the default ball     Public Jumpcircleview(Context context) { This(Context,NULL);//Can be directly new} Public Jumpcircleview(context context, AttributeSet attrs) { This(Context, Attrs,0);//Can be used in XML files} Public Jumpcircleview(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr);        TypedArray a = Context.obtainstyledattributes (Attrs, R.styleable.jumpcircleview, defstyleattr, R.style.apptheme);        Custom_size = A.getdimensionpixelsize (r.styleable.jumpcircleview_size, size);        Custom_background = A.getcolor (R.styleable.jumpcircleview_background_color, Default_color);        A.recycle ();    Init (); }Private void Init() {Mpaint =NewPaint ();        Mpaint.setcolor (Custom_background); Mpaint.setantialias (true);    Mpaint.setstyle (Paint.Style.FILL); }@Override    protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {intWidthmode = Measurespec.getmode (Widthmeasurespec);intWidthsize = Measurespec.getsize (Widthmeasurespec);intHeightmode = Measurespec.getmode (Heightmeasurespec);intHeightsize = Measurespec.getsize (Heightmeasurespec);intMeasuredheight, Measuredwidth;if(Widthmode = = measurespec.exactly)        {measuredwidth = widthsize; }Else{measuredwidth = SIZE; }if(Heightmode = = measurespec.exactly)        {measuredheight = heightsize; }Else{measuredheight = SIZE;    } setmeasureddimension (Measuredwidth, measuredheight); }@Override    protected void OnLayout(BooleanChangedintLeftintTopintRightintBottom) {mheight = GetHeight ();    Mwidth = GetWidth (); }PrivateValueanimator Manimator;@Override    protected void OnDraw(Canvas canvas) {/* parameter * Center x Center y radius (here to change) brush * */Canvas.drawcircle (Mwidth/2, Mheight/2, Custom_size * scale, mpaint); } Public void startanimation() {manimator = Valueanimator.offloat (1,2);//From 1-2 constantly changingManimator.addupdatelistener (NewValueanimator.animatorupdatelistener () {@Override             Public void onanimationupdate(Valueanimator animation) {//Get the value of changing every momentScale = (float) Animation.getanimatedvalue ();            Postinvalidate (); }        });//Repeat-1 means infinite loopManimator.setrepeatcount (-1);//Repeat mode, RESTART: Restart REVERSE: Resume initial state and start againManimator.setrepeatmode (Valueanimator.reverse);    Manimator.start (); } Public void stopanimation() {if(Manimator! =NULL) {//Manimator.end ();Manimator.cancel (); }    }//@Override//public boolean ontouchevent (Motionevent event) {//switch (Event.getaction ()) {//Case Motionevent.action_down://Manimator.end ();////int scale = (int) manimator.getanimatedvalue ();//Case Motionevent.action_move://break;//Case MOTIONEVENT.ACTION_UP:////startanimation ();//Manimator.start ();//break;//        }//return true;//    }    @Override    protected void Ondetachedfromwindow() {Super. Ondetachedfromwindow ();//Remove from view        //Close animationManimator.end (); }@Override    protectedParcelableonsaveinstancestate() {return Super. Onsaveinstancestate (); }@Override    protected void onrestoreinstancestate(parcelable State) {Super. Onrestoreinstancestate (state);        }} using Jumpview.startanimation (); Jumpview.setontouchlistener (NewView.ontouchlistener () {@Override             Public Boolean OnTouch(View V, motionevent event) {Switch(Event.getaction ()) { CaseMotionEvent.ACTION_DOWN:jumpView.stopAnimation (); CaseMotionevent.action_move: Break; CaseMotionEvent.ACTION_UP:jumpView.startAnimation (); Break; }return true; }        });

The note is already very clear, and it should be noted that the ONTOUCHEVETN can be overridden in the view, or it can be written in place of the call. However: if you want to listen to gestures, you will generally think of Ontouch, but we find that the Ontouch event of view is just action-down. Cause: return False in Ontouch. Workaround: 1, return true2, add android:longclickable= "true" to the XML layout are not exactly equivalent. Return true means that the view will continue to handle the lift event without passing the time to the parent view ——— This also means that only one view can continue to listen to the touch event and therefore must be aware of the Ontouch event's delivery process. A child view is passed to the parent view, and if return is false, it can be passed to the parent view,true. Gestures are best done in the dispatchtouchevent of the activity, which cannot be masked by a quilt view. In addition Ontouch if true, the onclick cannot be monitored

Customizing View and Event handling

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.