Android custom component series [1] -- custom View and ViewGroup

Source: Internet
Author: User

The View class is the parent class of ViewGroup. ViewGroup has all the features of View. ViewGroup is mainly used to act as the View container and manage the View as its own child, of course, the child can also be of the ViewGroup type.

The View class is generally used for drawing operations. It overrides its onDraw method, but it cannot contain other components and does not have the addView (View view) method.

ViewGroup is a component container that can contain any component, but must override onLayout (boolean changed, int l, int t, int r, int B) and onMesure (int widthMesureSpec, int heightMesureSpec) method. otherwise, components added to ViewGroup are not displayed.

package com.example.testrefreshview;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.view.ViewGroup;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new MyViewGroup(this));}public class MyViewGroup extends ViewGroup {public MyViewGroup(Context context) {super(context);Button button1 = new Button(context);button1.setText("button1");Button button2 = new Button(context);button2.setText("button2");TextView textView = new TextView(context);textView.setText("textView");addView(button1);addView(button2);addView(textView);}@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3,int arg4) {}}}

The layout (int left, int top, int right, int bottom) method of the View is used to place the view in the specified position of the parameter. Therefore, if we are in the Custom ViewGroup :: traverse each sub-view in onLayout and use view. layout () specifies its location, and each sub-View calls onLayout again, which constitutes a recursive call process.

If you override the onDraw method in ViewGroup, you must call this in the constructor. setWillNoDraw (flase); in this case, the system will call the overwritten onDraw (Canvas cancas) method. Otherwise, the system will not call the onDraw (Canvas canvas) method.

Modify the above Code to display it.

package com.example.testrefreshview;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(new MyViewGroup(this));}public class MyViewGroup extends ViewGroup {public MyViewGroup(Context context) {super(context);Button button1 = new Button(context);button1.setText("button1");Button button2 = new Button(context);button2.setText("button2");TextView textView = new TextView(context);textView.setText("textView");addView(button1);addView(button2);addView(textView);}@Overrideprotected void onLayout(boolean arg0, int arg1, int arg2, int arg3,int arg4) {int childCount = getChildCount();int left = 0;int top = 10;for (int i = 0; i < childCount; i++) {View child = getChildAt(i);child.layout(left, top, left + 60, top + 60);top += 70;}}}}

Let's look at another piece of code:

@ Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {int childCount = getChildCount (); // set the ViewGroup size to int specSize_width = MeasureSpec. getSize (widthMeasureSpec); int specSize_height = MeasureSpec. getSize (heightMeasureSpec); setMeasuredDimension (specSize_width, specSize_height); for (int I = 0; I <childCount; I ++) {View childView = getChildAt (I); childView. measure (80, 80 );}}

The onMeasure method can be rewritten to not only specify the ViewGroup size, but also to specify the size for each sub-View through traversal, add the preceding code to the custom ViewGroup to assign the display width and height to each sub-View in the ViewGroup.

Let's move the sub-View. The Code is as follows:

public boolean onTouchEvent(MotionEvent ev) {final float y = ev.getY();switch(ev.getAction()) {case MotionEvent.ACTION_DOWN:mLastMotionY = y;break; case MotionEvent.ACTION_MOVE:int detaY = (int)(mLastMotionY - y);mLastMotionY = y;scrollBy(0, detaY);break; case MotionEvent.ACTION_UP:break;}return true;}

A scrollBy method is used above. Open the official API and you can see that the View class has the following two methods:


The two functions seem to be moving views. What are their differences? Let's look at this question.

First, we must understand that the Android View has no boundaries and the Canvas has no boundaries. However, when we draw a specific View, we perform some operations on the Canvas object. For example: translate (translation), clipRect (CUT), etc., in order to meet our requirements for drawing the Canvas object, we can call this borderless View "view coordinate"-it is not restricted by the physical screen. Normally, a Layout file is only the display area of the view. If it is exceeded, it cannot be displayed in the area of the parent view, we can call this boundary View "layout coordinates" ------ layout size allocated by the parent View to the Child view. In addition, the starting coordinate of a view on the screen is located at the starting point of the view coordinate, as shown in.


Because the layout coordinates can only display a specific part of the content, we can only move the coordinates of the layout coordinates to display any position of the View coordinates.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical"    android:background="#888888"><TextView    android:id="@+id/txt"    android:layout_width="300dip"    android:layout_height="120dip"    android:background="#cccccc"    android:text="textview" /><Button    android:id="@+id/btn"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:text="button" /></LinearLayout>

When I click the button to trigger the event, the following occurs:


After the click event is triggered in the code above, textView is executed. scrollTo (-200,-100); the two parameters in scrollTo are not the coordinate position, but the offset relative to the Coordinate Position of the view. Suppose we want to move to (200,100) the offset is (200,100)-(200) = (-100 ).

If we replace the above Code with scrollBy, we will find that after clicking the button multiple times, textview will be removed from the visible interface, because scrollBy is offset against our current coordinate.

Let's take a look at how these two methods are implemented in the source code:

    /**     * Set the scrolled position of your view. This will cause a call to     * {@link #onScrollChanged(int, int, int, int)} and the view will be     * invalidated.     * @param x the x position to scroll to     * @param y the y position to scroll to     */    public void scrollTo(int x, int y) {        if (mScrollX != x || mScrollY != y) {            int oldX = mScrollX;            int oldY = mScrollY;            mScrollX = x;            mScrollY = y;            invalidateParentCaches();            onScrollChanged(mScrollX, mScrollY, oldX, oldY);            if (!awakenScrollBars()) {                invalidate(true);            }        }    }
We can see that mScrollX = x; mScrollY = y;

    /**     * Move the scrolled position of your view. This will cause a call to     * {@link #onScrollChanged(int, int, int, int)} and the view will be     * invalidated.     * @param x the amount of pixels to scroll by horizontally     * @param y the amount of pixels to scroll by vertically     */    public void scrollBy(int x, int y) {        scrollTo(mScrollX + x, mScrollY + y);    }
You can see mScrollX + x, mScrollY + y;

MScrollX and mScrollY are the current offset relative to the view coordinate.







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.