精华内容
下载资源
问答
  • Android ViewGroup拦截触摸事件详解

    万次阅读 2014-10-01 21:29:13
    在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如ListView下拉刷新就是典型的触摸事件拦截的例子。触摸事件拦截就是在触摸事件被parent view拦截,而不会分发给其child,即使触摸发生在该child身上。被拦截的...

    前言

    在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如ListView下拉刷新就是典型的触摸事件拦截的例子。触摸事件拦截就是在触摸事件被parent view拦截,而不会分发给其child,即使触摸发生在该child身上。被拦截的事件会转到parent view的onTouchEvent方法中进行处理。但是这个交互过程还是挺复杂的,有多种情况,今天我们就来分析一下吧。这篇分析文章已经放了一段时间了,如果有任何问题请高人指出。


    触摸事件的分发

    简单来说触摸事件的分发会经过这么几个顺序,dispatchTouchEvent --> onInterceptTouchEvent --> onTouchEvent,事件拦截就在onInterceptTouchEvent方法中进行,在该方法中返回true即代表拦截触摸事件。触摸事件的分发是一个典型的隧道事件,即从上到下的过程。从视图树角度上来说,就是触摸事件会从父视图挨个传递到子视图。比如一个LinearLayout中又一个TextView,当触摸这个TextView时触摸事件会先打到LinearLayout,然后再到达TextView。如果LinearLayout将触摸事件拦截了,那么TextView就会收到一个CANCEL事件,其他触摸就收不到了。但是触摸事件的处理过程是一个冒泡事件,还是以上面的TextView为例,正常情况下,事件从上到下分发到TextView上,TextView则会对该事件进行处理,如果TextView处理了该事件,即TextView的dispatchTouchEvent返回了true, 那么该事件就被消费了。但是如果TextView的dispatchTouchEvent返回的是false, 则代表这个事件没有被处理,此时该事件就会从下到上(即从child 到 view group的过程)找parent view进行处理。如果parent view也没有处理,那么最终会交给Activity (如果是Activity窗口) 的onTouchEvent来处理。下面就是ViewGroup的事件分发过程,更详细的资料请参考Android Touch事件分发过程

    触摸事件的拦截

    ViewGroup对于事件的拦截是一个复杂的流程,如果你想对触摸事件进行拦截,那么你需要覆写onInterceptTouchEvent方法,并且返回true。然后后续的事件就会被转移到该ViewGroup的onTouchEvent方法进行处理,而在后续的事件处理过程中onInterceptTouchEvent中也不会收到后续事件,因此你也需要覆写onTouchEvent方法。我们首先看看onInterceptTouchEvent方法的官方说明 : 

    public boolean onInterceptTouchEvent (MotionEvent ev)

    Implement this method to intercept all touch screen motion events. This allows you to watch events as they are dispatched to your children, and take ownership of the current gesture at any point.

    Using this function takes some care, as it has a fairly complicated interaction with View.onTouchEvent(MotionEvent), and using it requires implementing that method as well as this one in the correct way. Events will be received in the following order:

    You will receive the down event here.
        The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing must happen in onTouchEvent() like normal.

    For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().

    If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.

    翻译如下 : 

    实现这个方法来拦截所有触摸事件。这会使得您可以监控到所有分发到你的子视图的事件,然后您可以随时控制当前的手势。
    使用这个方法您需要花些精力,因为它与View.onTouchEvent(MotionEvent)的交互非常复杂,并且要想使用这个功能还需要把当前ViewGroup的onTouchEvent方法和子控件的onTouchEvent方法正确地结合在一起使用。事件获取顺序如下:


    你将从这里开始接收ACTION_DOWN触摸事件。
    ACTION_DOWN触摸事件可以由该ViewGroup自己处理,也可以由它的子控件的onTouchEvent进行处理;这就意味着你需要实现onTouchEvent(MotionEvent)方法并且返回true,这样你才可以接收到后续的事件(以免会继续寻找父控件进行处理)。如果你在onTouchEvent(MotionEvent)返回了true,那么在onInterceptTouchEvent()方法中您将
    不会再收到后续的事件,所有这些后续的事件(例如您在ACTION_DOWN中返回了true,那么ACTION_MOVE, ACTION_UP这些成为后续事件)将会被本类的onTouchEvent(MotionEvent)方法中被处理。

    ************
    只要您在onInterceptTouchEvent方法中返回false,每个后续的事件(从当前事件到最后ACTION_UP事件)将会先分发到onInterceptTouchEvent中,然后再交给目标子控件的onTouchEvent处理 (前提是子控件的onTouchEvent返回是true )。

    如果在onInterceptTouchEvent返回true,
    onInterceptTouchEvent方法中将不会收到后续的任何事件,目标子控件中除了ACTION_CANCEL外也不会接收所有这些后续事件,所有的后续事件将会被交付到你自己的onTouchEvent()方法中
    ************

    触摸事件拦截示例

    TouchLayout类 ( ViewGroup )
    import android.content.Context;
    import android.support.v4.view.MotionEventCompat;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.widget.FrameLayout;
    import android.widget.Scroller;
    
    public class TouchLayout extends FrameLayout {
    
        private String TAG = TouchLayout.class.getSimpleName();
    
        public TouchLayout(Context context) {
            super(context);
    
        }
    
        public TouchLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public TouchLayout(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    //        setClickable(true);
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            boolean result = super.dispatchTouchEvent(ev) ;
     
            return result;
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            // 
            final int action = MotionEventCompat.getActionMasked(ev);
            // Always handle the case of the touch gesture being complete.
            if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
                // Do not intercept touch event, let the child handle it
                return false;
            }
    
            TouchUtils.showEventInfo(TAG + "#   onInterceptTouchEvent", action);
    
        
            return false;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            TouchUtils.showEventInfo(TAG + "# *** onTouchEvent", ev.getAction());
            Log.d(TAG, "### is Clickable = " + isClickable());
             return super.onTouchEvent(ev);
    //        return true;
        }
        
    }
    

    TouchTv ( View 类型)

    public class TouchTv extends TextView {
    
        private String TAG = TouchTv.class.getSimpleName();
    
        public TouchTv(Context context) {
            this(context, null);
        }
    
        public TouchTv(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public TouchTv(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    //        setClickable(true);
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            TouchUtils.showEventInfo(TAG + "#dispatchTouchEvent", ev.getAction());
            boolean result = super.dispatchTouchEvent(ev);
            Log.d(TAG, "### dispatchTouchEvent result = " + result);
            return result;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            TouchUtils.showEventInfo(TAG + "#onTouchEvent", ev.getAction());
            boolean result = super.onTouchEvent(ev);
            Log.d(TAG, "### onTouchEvent result = " + result);
            return result;
        }
    }
    
    Activity : 

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.touch_event_intercept);
    
            View myView = findViewById(R.id.my_button);
    
            ValueAnimator colorAnim = ObjectAnimator.ofInt(myView,
                    "backgroundColor", /* Red */
                    0xFFFF8080, /* Blue */0xFF8080FF);
            colorAnim.setDuration(3000);
            colorAnim.setEvaluator(new ArgbEvaluator());
            colorAnim.setRepeatCount(ValueAnimator.INFINITE);
            colorAnim.setRepeatMode(ValueAnimator.REVERSE);
            colorAnim.start();
    
            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(myView, "scaleX",
                    0.5f);
            objectAnimator.setDuration(3000);
            objectAnimator.setRepeatMode(ObjectAnimator.REVERSE);
            objectAnimator.start();
    
            Log.d("", "### Activiti中getWindow()获取的类型是 : " + this.getWindow());
    
            // state list
            StateListDrawable stateListDrawable = new StateListDrawable();
            stateListDrawable.addState(new int[] {
                    android.R.attr.state_enabled
            }, getResources().getDrawable(R.drawable.ic_launcher));
            stateListDrawable.addState(new int[] {
                    android.R.attr.state_pressed
            }, getResources().getDrawable(R.drawable.ic_launcher));
    
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            // Log.d("", "### activity dispatchTouchEvent");
            return super.dispatchTouchEvent(ev);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            TouchUtils.showEventInfo("activity onTouchEvent", event.getAction());
            return super.onTouchEvent(event);
        }
    
    }

    touch_event_intercept.xml : 

    <myview.TouchLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        tools:context="com.example.touch_event.MainActivity"
        tools:ignore="MergeRootFrame" >
    
        <myview.TouchTv
            android:id="@+id/my_button"
            android:layout_width="match_parent"
            android:layout_height="160dp"
            android:layout_gravity="center"
            android:layout_margin="20dp"
            android:background="#00aa00"
            android:gravity="center"
            android:text="@string/hello_world"
            android:textSize="30sp" />
    
    </myview.TouchLayout>


    情景分析



    以下的情景的触摸事件都是在TouchTv的范围内。

    情景1 

    条件 :  
    在TouchLayout的onInterceptTouchEvent中返回true进行事件拦截, 在TouchLayout的onTouchEvent中返回 true消费事件;

    说明 : 
    触摸事件被拦截 ,后续的事件不会进入到onInterceptTouchEvent ( If you return true from here, you will not receive any following events ),而直接进入TouchLayout的onTouchEvent方法进行处理。onTouchEvent返回true,表明事件被消费了,不会再冒泡给上面的Parent进行处理

    输出  : 
    // 事件拦截
    10-01 20:22:52.892: D/TouchLayout#   onInterceptTouchEvent(407): ### action -->  ACTION_DOWN
    // 处理
    10-01 20:22:52.892: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_DOWN
    // DOWN的后续事件不经过onInterceptTouchEvent,直接交给的onTouchEvent处理
    10-01 20:22:52.917: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:52.937: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:52.957: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:52.977: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:52.977: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:52.997: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:53.017: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_MOVE
    10-01 20:22:53.017: D/TouchLayout# *** onTouchEvent(407): ### action -->  ACTION_UP

    情景2

    条件 :  
    在TouchLayout的onInterceptTouchEvent中在ACTION_MOVE事件时返回true进行事件拦截, TouchTv的onTouchEvent中返回false,在TouchLayout的onTouchEvent中返回 true消费事件;

    说明 : 
    事件被拦截之前,会被分发给TouchTv的onTouchEvent进行处理;触摸事件被拦截之后 ,后续的事件不会进入到onInterceptTouchEvent,也不会交给TouchTv的onTouchEvent进行处理,而是直接进入TouchLayout的onTouchEvent方法进行处理。onTouchEvent返回true,表明事件被消费了,不会再冒泡给上面的Parent进行处理

    输出  : 
    // DOWN中没有对事件进行拦截,因此可以被TouchTv进行处理
    10-01 20:32:05.017: D/TouchLayout#   onInterceptTouchEvent(573): ### action -->  ACTION_DOWN
    // TouchTv事件分发
    10-01 20:32:05.017: D/TouchTv#dispatchTouchEvent(573): ### action -->  ACTION_DOWN
    // TouchTv对事件进行处理,TouchTv的onTouchEvent返回false,导致事件交给TouchLayout的onTouchEvent处理
    10-01 20:32:05.017: D/TouchTv#onTouchEvent(573): ### action -->  ACTION_DOWN
    // TouchLayout的onTouchEvent处理DOWN事件
    10-01 20:32:05.017: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_DOWN
    // TouchLayout的onTouchEvent处理后续事件
    10-01 20:32:05.062: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_MOVE
    10-01 20:32:05.082: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_MOVE
    10-01 20:32:05.267: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_MOVE
    10-01 20:32:05.287: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_MOVE
    10-01 20:32:05.307: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_MOVE
    10-01 20:32:05.307: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_MOVE
    10-01 20:32:05.312: D/TouchLayout# *** onTouchEvent(573): ### action -->  ACTION_UP
    

    情景3

    条件 :  
    在TouchLayout的onInterceptTouchEvent中返回true进行事件拦截, 但在TouchLayout的onTouchEvent中返回FALSE, 导致事件没有被消费;

    说明 : 
    触摸事件被拦截 ,后续的事件不会进入到onInterceptTouchEvent,而直接进入TouchLayout的onTouchEvent方法进行处理。onTouchEvent返回false 表明事件没有被消费,需要交给parent处理,如果最终该事件没有被处理,那么事件交给Activity的onTouchEvent处理。

    输出  : 
    // 事件拦截onInterceptTouchEvent
    10-01 20:16:03.617: D/TouchLayout#   onInterceptTouchEvent(32675): ### action -->  ACTION_DOWN
    // 事件处理onTouchEvent
    10-01 20:16:03.617: D/TouchLayout# *** onTouchEvent(32675): ### action -->  ACTION_DOWN
    // TouchLayout的dispatchTouchEvent最终返回了false,
    10-01 20:16:03.617: D/TouchLayout(32675): ### dispatchTouchEvent, return false
    // 事件没有被处理,最终交给了Activity的onTouchEvent处理
    10-01 20:16:03.617: D/activity onTouchEvent(32675): ### action -->  ACTION_DOWN
    10-01 20:16:03.697: D/activity onTouchEvent(32675): ### action -->  ACTION_MOVE
    10-01 20:16:03.712: D/activity onTouchEvent(32675): ### action -->  ACTION_MOVE
    10-01 20:16:03.732: D/activity onTouchEvent(32675): ### action -->  ACTION_MOVE
    10-01 20:16:03.882: D/activity onTouchEvent(32675): ### action -->  ACTION_MOVE
    10-01 20:16:03.897: D/activity onTouchEvent(32675): ### action -->  ACTION_MOVE
    10-01 20:16:03.917: D/activity onTouchEvent(32675): ### action -->  ACTION_UP

    情景4

    条件 :  
    在TouchLayout的onInterceptTouchEvent中返回FALSE,不对触摸进行事件拦截, TouchLayout的onTouchEvent中返回true,但在TouchTv的onTouchEvent中返回FALSE, 导致事件没有被消费;

    说明 : 
    触摸事件不进行拦截,因此事件最终进入到TouchTv的 onTouchEvent,但其返回false 表明事件没有被消费,需要交给parent处理,如果最终该事件没有被处理,那么事件交给Activity的onTouchEvent处理。

    输出  : 

    // TouchLayout不对事件进行拦截
    10-01 20:43:04.682: D/TouchLayout#   onInterceptTouchEvent(814): ### action -->  ACTION_DOWN
    // 事件被TouchTv分发
    10-01 20:43:04.682: D/TouchTv#dispatchTouchEvent(814): ### action -->  ACTION_DOWN
    // 事件被TouchTv处理
    10-01 20:43:04.682: D/TouchTv#onTouchEvent(814): ### action -->  ACTION_DOWN
    // 事件被TouchTv的处理结果为false,因此该事件需要找parent来处理
    10-01 20:43:04.682: D/TouchTv(814): ### dispatchTouchEvent result = false
    // 事件被交给TouchTv的parent的onTouchEvent处理,即TouchLayout的onTouchEvent,该方法返回true
    // 因此后续事件继续交给TouchLayout处理
    10-01 20:43:04.682: D/TouchLayout# *** onTouchEvent(814): ### action -->  ACTION_DOWN
    10-01 20:43:04.727: D/TouchLayout# *** onTouchEvent(814): ### action -->  ACTION_MOVE
    10-01 20:43:04.747: D/TouchLayout# *** onTouchEvent(814): ### action -->  ACTION_MOVE
    10-01 20:43:04.872: D/TouchLayout# *** onTouchEvent(814): ### action -->  ACTION_MOVE
    10-01 20:43:04.892: D/TouchLayout# *** onTouchEvent(814): ### action -->  ACTION_MOVE
    10-01 20:43:04.892: D/TouchLayout# *** onTouchEvent(814): ### action -->  ACTION_UP


    情景5

    条件 :  
    在TouchLayout的onInterceptTouchEvent中返回FALSE,不对触摸进行事件拦截, 但在TouchTv的onTouchEvent中返回true, 导致事件被消费;

    说明 : 
    触摸事件不进行拦截,因此事件最终进入到TouchTv的 onTouchEvent,但其返回true 表明事件被消费了,那么后续事件将会先到TouchLayout的onInterceptTouchEvent,然后再分发给TouchTv。原文描述为 : For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().

    输出  : 

    // TouchLayout不拦截事件,因此事件分发给TouchTv进行处理,而TouchTv的处理结果为true,因此后续的事件将会先从
    // TouchLayout的onInterceptTouchEvent再到TouchTv的onTouchEvent
    10-01 20:48:49.612: D/TouchLayout#   onInterceptTouchEvent(1030): ### action -->  ACTION_DOWN
    // TouchTv处理事件
    10-01 20:48:49.612: D/TouchTv#dispatchTouchEvent(1030): ### action -->  ACTION_DOWN
    10-01 20:48:49.612: D/TouchTv#onTouchEvent(1030): ### action -->  ACTION_DOWN
    10-01 20:48:49.612: D/TouchTv(1030): ### dispatchTouchEvent result = true
    // 后续事件从TouchLayout的onInterceptTouchEvent再到TouchTv的onTouchEvent
    10-01 20:48:49.697: D/TouchLayout#   onInterceptTouchEvent(1030): ### action -->  ACTION_MOVE
    10-01 20:48:49.697: D/TouchTv#dispatchTouchEvent(1030): ### action -->  ACTION_MOVE
    10-01 20:48:49.697: D/TouchTv#onTouchEvent(1030): ### action -->  ACTION_MOVE
    10-01 20:48:49.697: D/TouchTv(1030): ### dispatchTouchEvent result = true
    10-01 20:48:49.717: D/TouchLayout#   onInterceptTouchEvent(1030): ### action -->  ACTION_MOVE
    10-01 20:48:49.717: D/TouchTv#dispatchTouchEvent(1030): ### action -->  ACTION_MOVE
    10-01 20:48:49.717: D/TouchTv#onTouchEvent(1030): ### action -->  ACTION_MOVE
    10-01 20:48:49.717: D/TouchTv(1030): ### dispatchTouchEvent result = true
    // UP事件直接在TouchTv中进行分发
    10-01 20:48:49.782: D/TouchTv#dispatchTouchEvent(1030): ### action -->  ACTION_UP
    10-01 20:48:49.782: D/TouchTv#onTouchEvent(1030): ### action -->  ACTION_UP
    10-01 20:48:49.782: D/TouchTv(1030): ### dispatchTouchEvent result = true

    情景6

    条件 :  
    在TouchLayout的onInterceptTouchEvent中的DOWN事件中返回FALSE,但在MOVE事件中返回true, 且TouchTv的onTouchEvent返回true。

    说明 : 
    触摸事件对DOWN事件不进行拦截,因此TouchTv可以正常的处理。但是在MOVE时对事件进行了拦截,那么TouchTv就无法接收到MOVE以及后面的事件了,它会收到一个CANCEL事件,后续的事件将会被TouchLayout的onTouchEvent进行处理。( If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here. )

    输出  : 
    // TouchLayout不对DOWN进行拦截
    10-01 20:56:37.642: D/TouchLayout#   onInterceptTouchEvent(1205): ### action -->  ACTION_DOWN
    // TouchTv分发与处理DOWN事件
    10-01 20:56:37.642: D/TouchTv#dispatchTouchEvent(1205): ### action -->  ACTION_DOWN
    10-01 20:56:37.642: D/TouchTv#onTouchEvent(1205): ### action -->  ACTION_DOWN
    10-01 20:56:37.642: D/TouchTv(1205): ### dispatchTouchEvent result = true
    // TouchLayout对MOVE事件进行拦截
    10-01 20:56:37.712: D/TouchLayout#   onInterceptTouchEvent(1205): ### action -->  ACTION_MOVE
    // TouchTv收到一个CANCEL事件,然后不会不到MOVE以及后续的事件
    10-01 20:56:37.712: D/TouchTv#dispatchTouchEvent(1205): ### action -->  ACTION_CANCEL
    10-01 20:56:37.712: D/TouchTv#onTouchEvent(1205): ### action -->  ACTION_CANCEL
    10-01 20:56:37.712: D/TouchTv(1205): ### dispatchTouchEvent result = true
    // MOVE以及后续事件被TouchLayout处理
    10-01 20:56:37.727: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:37.747: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:37.762: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:37.777: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:37.797: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:37.997: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:38.012: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_MOVE
    10-01 20:56:38.017: D/TouchLayout# *** onTouchEvent(1205): ### action -->  ACTION_UP

    总结

    以上的几种情况就是我们经常遇到的了,总结起来有几个重要的点 :

    1、如果Parent ViewGroup的onInterceptTouchEvent返回false, 并且触摸的目标view对于触摸事件的处理结果返回的是true,那么后续事件会先经过parent 的onInterceptTouchEvent, 然后再交给目标view进行处理;

    2、如果Parent ViewGroup的onInterceptTouchEvent返回true,即对事件进行拦截,那么事件将不会再经过onInterceptTouchEvent,而是直接进入到onTouchEvent进行处理;如果onTouchEvent返回true,则表示该事件被处理了;如果返回FALSE,则代表事件没有被处理,那么事件会被上交给它的parent来处理,如果没有parent来处理,那么最终会交给Activity来处理;

    3、如果用户在触摸的某个事件才拦截,那么目标view会收到一个CANCEL事件,然后后续的事件不会再交给目标view,而被转交给Parent的onTouchEvent方法进行处理。比如情景6当中,在TouchLayout的DOWN时不对事件进行拦截,这时事件会被TouchTv正常处理。但是在MOVE时事件被拦截了,此时TouchTv收到了一个CANCEL事件,MOVE以及后续的事件就交给了TouchLayout进行处理。这个情景就是我们做下拉刷新时要用的场景了。
    我们结合ViewGroup的事件分发过程来验证吧。代码如下 : 
    /** 
     * {@inheritDoc} 
     */  
    @Override  
    public boolean dispatchTouchEvent(MotionEvent ev) {  
        if (!onFilterTouchEventForSecurity(ev)) {  
            return false;  
        }  
      
        final int action = ev.getAction();  
        final float xf = ev.getX();  
        final float yf = ev.getY();  
        final float scrolledXFloat = xf + mScrollX;  
        final float scrolledYFloat = yf + mScrollY;  
        final Rect frame = mTempRect;  
        // 是否禁用拦截,如果为true表示不能拦截事件;反之,则为可以拦截事件  
        boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;  
        // ACTION_DOWN事件,即按下事件  
        if (action == MotionEvent.ACTION_DOWN) {  
            if (mMotionTarget != null) {  
                mMotionTarget = null;  
            }  
            // If we're disallowing intercept or if we're allowing and we didn't  
            // intercept。如果不允许事件拦截或者不拦截该事件,那么执行下面的操作  
            if (disallowIntercept || !onInterceptTouchEvent(ev))         // 1、是否禁用拦截、是否拦截事件的判断  
                // reset this event's action (just to protect ourselves)  
                ev.setAction(MotionEvent.ACTION_DOWN);  
                // We know we want to dispatch the event down, find a child  
                // who can handle it, start with the front-most child.  
                final int scrolledXInt = (int) scrolledXFloat;  
                final int scrolledYInt = (int) scrolledYFloat;  
                final View[] children = mChildren;  
                final int count = mChildrenCount;  
      
                for (int i = count - 1; i >= 0; i--)        // 2、迭代所有子view,查找触摸事件在哪个子view的坐标范围内  
                    final View child = children[i];  
                    // 该child是可见的  
                    if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE  
                            || child.getAnimation() != null) {  
                        // 3、获取child的坐标范围  
                        child.getHitRect(frame);                 
                        // 4、判断发生该事件坐标是否在该child坐标范围内  
                        if (frame.contains(scrolledXInt, scrolledYInt))      
                            // offset the event to the view's coordinate system  
                            final float xc = scrolledXFloat - child.mLeft;  
                            final float yc = scrolledYFloat - child.mTop;  
                            ev.setLocation(xc, yc);  
                            child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
                            // 5、child处理该事件,如果返回true,那么mMotionTarget为该child。正常情况下,  
                            // dispatchTouchEvent(ev)的返回值即onTouchEcent的返回值。因此onTouchEcent如果返回为true,  
                            // 那么mMotionTarget为触摸事件所在位置的child。  
                            if (child.dispatchTouchEvent(ev))       
                                // 6、 mMotionTarget为该child
                                mMotionTarget = child;  
                                return true;  
                            }  
                   
                        }  
                    }  
                }  
            }  
        }// end if  
      
        boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||  
                (action == MotionEvent.ACTION_CANCEL);  
      
        if (isUpOrCancel) {  
            // Note, we've already copied the previous state to our local  
            // variable, so this takes effect on the next event  
            mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;  
        }  
      
      	// 触摸事件的目标view, 即触摸所在的view
        final View target = mMotionTarget;  
        // 7、如果mMotionTarget为空,那么执行super.super.dispatchTouchEvent(ev),  
        // 即View.dispatchTouchEvent(ev),就是该View Group自己处理该touch事件,只是又走了一遍View的分发过程而已.  
        // 拦截事件或者在不拦截事件且target view的onTouchEvent返回false的情况都会执行到这一步.  
        if (target == null) {  
            // We don't have a target, this means we're handling the  
            // event as a regular view.  
            ev.setLocation(xf, yf);  
            if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {  
                ev.setAction(MotionEvent.ACTION_CANCEL);  
                mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
            }  
            return super.dispatchTouchEvent(ev);  
        }  
     
        // 8、如果没有禁用事件拦截,并且onInterceptTouchEvent(ev)返回为true,即进行事件拦截.  ( 在某个事件时拦截的情形 )  
        if (!disallowIntercept && onInterceptTouchEvent(ev)) {  
            final float xc = scrolledXFloat - (float) target.mLeft;  
            final float yc = scrolledYFloat - (float) target.mTop;  
            mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
            ev.setAction(MotionEvent.ACTION_CANCEL);  
            ev.setLocation(xc, yc);  
            //   
            if (!target.dispatchTouchEvent(ev)) {  
                // target didn't handle ACTION_CANCEL. not much we can do  
                // but they should have.  
            }  
            // clear the target  
            mMotionTarget = null;  
            // Don't dispatch this event to our own view, because we already  
            // saw it when intercepting; we just want to give the following  
            // event to the normal onTouchEvent().  
            return true;  
        }  
      
        if (isUpOrCancel) {  
            mMotionTarget = null;  
        }  
      
        // finally offset the event to the target's coordinate system and  
        // dispatch the event.  
        final float xc = scrolledXFloat - (float) target.mLeft;  
        final float yc = scrolledYFloat - (float) target.mTop;  
        ev.setLocation(xc, yc);  
      
        if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {  
            ev.setAction(MotionEvent.ACTION_CANCEL);  
            target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;  
            mMotionTarget = null;  
        }  
        // 9、事件不拦截,且target view在ACTION_DOWN时返回true,那么后续事件由target来处理事件  
        return target.dispatchTouchEvent(ev);  
    }  
    如果不对事件进来拦截,且TouchTv对事件的处理返回true,那么在DOWN事件时,mMotionTarget就是TouchTv,后续的事件就会通过注释9来处理,即直接交给TouvhTv来处理。如果在DOWN时就拦截事件,那么mMotionTarget为空,则会执行注释7出的代码,一直调用super.dispatchTouchEvent处理事件,即调用本类的事件处理,最终会调用onTouchEvent方法。如果在DOWN时不拦截,MOVE时拦截,那么会引发注释8的代码,target view收到一个cancel事件,且mMotionTarget被置空,后续事件在注释7出的代理进行处理,即在自己的onTouchEvent中进行处理。
    展开全文
  • Android ViewGroup中addView方法使用

    千次阅读 2018-05-21 19:41:43
    AndroidViewGroup 中的添加子控件的方法addVIew方法 //child:要添加的view public void addView(View child) ; //child:要添加的View index:view在父布局中位于第几个 public void addView(View child, int ...

    Android 中ViewGroup 中的添加子控件的方法addVIew方法

    //child:要添加的view
    public void addView(View child) ;
    
    //child:要添加的View  index:view在父布局中位于第几个
    public void addView(View child, int index);
    
    //child:要添加的View  width/height:在父布局中的宽高
    public void addView(View child, int width, int height);
    
    //child:要添加的View  params:在父布局中的参数
    public void addView(View child, LayoutParams params);
    //child:要添加的View  ;index:view在父布局中位于第几个; params:在父布局中的参数
    public void addView(View child, int index, LayoutParams params);

    index 参数在linearlayout中使用addView的时候,如果Linearlayout方向是vertical 垂直, index代表添Linearlayout中第几个子view例如

    布局文件:

    <?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="com.phone.test_addview.MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:id="@+id/content"
            >
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="1111111111"
                android:gravity="center"
                android:layout_margin="20dp"
                android:textSize="18sp"
                android:textColor="#f1f"
            />
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="2222222222"
                android:gravity="center"
                android:layout_margin="20dp"
                android:textSize="18sp"
                android:textColor="#f1f"
                />
        </LinearLayout>
    </LinearLayout>
    

    Activity文件:

    package com.phone.test_addview;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.LinearLayout;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            LinearLayout content= (LinearLayout) findViewById(R.id.content);
            Button button =new Button(this);
            button.setText("确定");
            LinearLayout.LayoutParams param=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            param.gravity= Gravity.CENTER;
            content.addView(button,1,param);
        }
    }
    

    这里写图片描述

    以上代码就是在两个TextView中间添加一个Button,index参数-1代表就是在最后添加,0代表第一个子元素,1是第二个以此类推

    展开全文
  • Android ViewGroup系列控件的使用

    千次阅读 2014-02-17 18:26:53
    一、 ViewGroup1.1 概述  定义  public abstract class ViewGroup extends View implements ViewParent, ViewManager  ...import android.view.ViewGroup;  子类信息  View  |___ ViewGroup   
    一、            ViewGroup1.1         概述 
    
    定义 
    public abstract class ViewGroup extends View implements ViewParent, ViewManager 
    所在的包 
    import android.view.ViewGroup; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
           |      |___ AbsListView 
           |      |      |___ GridView 
           |      |      |___ ListView 
           |      |             |___ ExpandableListView 
           |      |___ AbsSpinner 
           |             |___ Gallery 
           |             |___ Spinner 
           |___ FrameLayout 
           |      |___ DatePicker 
           |      |___ TimePicker 
           |      |___ MediaController 
           |      |___ ScrollView 
           |      |___ TabHost 
           |      |___ ViewAnimator 
           |             |___ ViewFlipper 
           |             |___ ViewSwitcher 
           |                    |___ ImageSwitcher 
           |                    |___ TextSwitcher 
           |___ LinearLayout 
           |      |___ RadioGroup 
           |      |___ TabWidget 
           |      |___ TableLayout 
           |      |___ TableRow 
           |      |___ ZoomControls 
           |___ RelativeLayout 
           |      |___ DialerFilter 
           |      |___ TwoLineListItem 
           |___ AbsoluteLayout 
                  |___ WebView 
    ViewGroup继承View,是一组view的集合,通过addView()来添加child view,removeView()、removeAllViews()等删除child view。addView()加入的view存为数组,初始化数组大小为12,超过大小时每次增加12,每一个index对应一个view,可以通过getChildAt()、indexOfChild()来获取view和index,getChildCount()获取总child数。 
    内部类LayoutParams来管理ViewGroup的所占区域大小。 
    FILL_PARENT:填充满parent的宽或高 
    WRAP_CONTENT:内容的实际大小加边距 
    offsetChildrenTopAndBottom()、setPadding()来设置边距。 
    1.2         部分方法 
    void addView(View child) 
    void addView(View child, int index) 
    void addView(View child, int width, int height) 
    void addView(View child, LayoutParams params) 
    void addView(View child, int index, LayoutParams params) 
    void removeView(View view) 
    void removeViewAt(int index) 
    void removeViews(int start, int count) 
    void removeAllViews() 
    void removeViewInLayout(View view) 
    void removeViewsInLayout(int start, int count) 
    void removeAllViewsInLayout() 
    增加删除child view 
    void offsetChildrenTopAndBottom(int offset) 
    设置垂直方向顶部和底部的偏移,单位象素 
    int getChildCount() 
    int indexOfChild(View child) 
    View getChildAt(int index) 
    void setDescendantFocusability(int focusability) 
    int getDescendantFocusability() 
    ViewGroup.FOCUS_BEFORE_DESCENDANTS 
    先于子孙获得focus 
    ViewGroup.FOCUS_AFTER_DESCENDANTS 
    子孙都不需要focus时viewgroup才获得 
    ViewGroup.FOCUS_BLOCK_DESCENDANTS 
    void setClipChildren(boolean clipChildren) 
    void setClipToPadding(boolean clipToPadding) 
    true:滚动时child不可以绘制到padding区域,即剪裁掉 
    false:滚动时child可以绘制到padding区域 
    void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) 
    设置child有add或remove时触发的监听器 
    void startLayoutAnimation() 
    运行动画 
    void scheduleLayoutAnimation() 
    设置动画状态,刷新时运行动画 
    void setLayoutAnimation(LayoutAnimationController controller) 
    LayoutAnimationController getLayoutAnimation() 
    设置布局动画,在child第一次布局时运行动画 
    void setLayoutAnimationListener(Animation.AnimationListener animationListener) 
    Animation.AnimationListener getLayoutAnimationListener() 
    设置动画播放开始、结束、重播时触发的监听器 
    boolean isAnimationCacheEnabled() 
    void setAnimationCacheEnabled(boolean enabled) 
    boolean isAlwaysDrawnWithCacheEnabled() 
    void setAlwaysDrawnWithCacheEnabled(boolean always) 
    int getPersistentDrawingCache() 
    void setPersistentDrawingCache(int drawingCacheToKeep) 
    1.3         ViewGroup.LayoutParams 
    public static class LayoutParams 
    ViewGroup.LayoutParams 
    |___ ViewGroup.MarginLayoutParams 
    |      |___ FrameLayout.LayoutParams 
    |      |___ LinearLayout.LayoutParams 
    |      |      |___ RadioGroup.LayoutParams 
    |      |      |___ TableLayout.LayoutParams 
    |      |      |___ TableRow.LayoutParams 
    |      |___ RelativeLayout.LayoutParams 
    |___ AbsoluteLayout.LayoutParams 
    |___ AbsListView.LayoutParams 
    |___ Gallery.LayoutParams 
    |___ WindowManager.LayoutParams 
    public int width;     //指定view的宽高 
    public int height; 
    public LayoutAnimationController.AnimationParameters layoutAnimationParameters; 
    ViewGroup.LayoutParams.FILL_PARENT 
    ViewGroup.LayoutParams.WRAP_CONTENT 
    public LayoutParams(Context c, AttributeSet attrs) 
    public LayoutParams(int width, int height) 
    public LayoutParams(LayoutParams source) 
    LayoutParams() 
    1.4         ViewGroup. MarginLayoutParams 
    public static class MarginLayoutParams extends ViewGroup.LayoutParams 
    public int leftMargin;     //在ViewGroup.LayoutParams基础上增加4个方向边距 
    public int topMargin; 
    public int rightMargin; 
    public int bottomMargin; 
    public MarginLayoutParams(Context c, AttributeSet attrs) 
    public MarginLayoutParams(int width, int height) 
    public MarginLayoutParams(MarginLayoutParams source) 
    public MarginLayoutParams(LayoutParams source) 
    public void setMargins(int left, int top, int right, int bottom) 
            Margin        Padding、大小为设置的width, height,背景绘制的区域        实体大小 

    通过ViewGroup.LayoutParams设置width,height 
    View.setLayoutParams(ViewGroup.LayoutParams params); 
    通过ViewGroup.MarginLayoutParams设置margin 
    ViewGroup.MarginLayoutParams.setMargins(int left, int top, int right, int bottom); 
    ViewGroup.MarginLayoutParams.leftMargin 
    通过View. setPadding(int left, int top, int right, int bottom); 设置padding 
    白色区域大小:    width+ leftMargin+ rightMargin 
                                height+ topMargin+ bottomMargin 
    橙色区域大小:    width 
                                height 
    绿色区域大小:    width- leftPadding- rightPadding 
                                height- topPadding- bottomPadding 

    二、            AdapterView<T extends Adapter>2.1         概述 
    定义 
    public abstract class AdapterView<T extends Adapter> extends ViewGroup 
    包路径 
    import android.widget.AdapterView; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsListView 
                  |      |___ GridView 
                  |      |___ ListView 
                  |             |___ ExpandableListView 
                  |___ AbsSpinner 
                         |___ Gallery 
                         |___ Spinner 
    AdapterView继承ViewGroup,但AdapterView的child view由Adapter决定,不能通过addView()来添加。 
    setAdapter()来设置Adapter,getAdapter()获取。 
    2.2         部分方法 
    void addView(View child) 
    void addView(View child, int index) 
    void addView(View child, LayoutParams params) 
    void addView(View child, int index, LayoutParams params) 
    void removeView(View child) 
    void removeViewAt(int index) 
    void removeAllViews() 
    不支持添加删除view,使用则抛出UnsupportedOperationException异常 
    void setOnClickListener(OnClickListener l) 
    不支持,抛出异常RuntimeException 
    abstract T getAdapter() 
    abstract void setAdapter(T adapter) 
    设置child的数据和view 
    int getCount() 
    int getPositionForView(View view) 
    long getItemIdAtPosition(int position) 
    Object getItemAtPosition(int position) 
    返回Object不一定就是一个item的view,跟getAdapter().getItem(position)等效 
    要想获得view应getAdapter().getView(position, convertView, parent) 
    abstract View getSelectedView() 
    int getSelectedItemPosition() 
    long getSelectedItemId() 
    Object getSelectedItem() 
    abstract void setSelection(int position) 
    int getFirstVisiblePosition() 
    屏幕上可见的第一项的position,部分可见也算 
    int getLastVisiblePosition() 
    屏幕上可见的最后一项的position,部分可见也算 
    void setFocusable(boolean focusable) 
    void setFocusableInTouchMode(boolean focusable) 
    void setOnItemClickListener(OnItemClickListener listener) 
    final OnItemClickListener getOnItemClickListener() 
    设置item点击监听器 
    boolean performItemClick(View view, int position, long id) 
    调用item点击监听器设置的回调函数 
    void setOnItemLongClickListener(OnItemLongClickListener listener) 
    final OnItemLongClickListener getOnItemLongClickListener() 
    设置item长按监听器 
    void setOnItemSelectedListener(OnItemSelectedListener listener) 
    final OnItemSelectedListener getOnItemSelectedListener() 
    设置item被选择时触发的监听器 
    public void setTextFilterEnabled(boolean textFilterEnabled) 
    public boolean isTextFilterEnabled() 
    开启或关闭过滤窗口,开启时,键盘输入显示在屏幕下方一半透明黑色区域,根据输入过滤掉不包含输入文字的项 

    二、            Adapter3.1         概述 
    定义 
    public interface Adapter 
    包路径 
    import android.widget.Adapter; 
    SpinnerAdapter 
    ListAdapter 
    HeaderViewListAdapter 
    BaseAdapter 
    WrapperListAdapter 
    CursorAdapter 
    ArrayAdapter<T> 
    SimpleAdapter 
    Adapter 
    ResourceCursorAdapter 
    SimpleCursorAdapter 
    黑色文字为接口红色文字为类斜体字为抽象类 
    子类信息 
    Adapter是AdapterView和数据间的桥梁,提供访问每项数据的接口,并为每项创建一个view。 
    3.2         部分方法 
    void unregisterDataSetObserver(DataSetObserver observer); 
    void registerDataSetObserver(DataSetObserver observer) 
    注册一个observer,当该Adapter对象的数据变化时调用。 
    int getCount() 
    Object getItem(int position) 
    long getItemId(int position)      
    boolean hasStableIds() 
    item的id是否稳定。稳定则数据变化时item 的id不变 
    View getView(int position, View convertView, ViewGroup parent) 
    返回显示position项数据的view,可以手动创建一个view也可以通过xml layout文件创建。 
    position          第position项 
    convertView   可以为null,送入一个view,如果这个view不能转换为需要显示的view则创建一个新的view 
    parent            返回的view加入parent的ViewGroup 
    int getViewTypeCount() 
    getView()返回view的种数,如果都返回同一类的view则getViewTypeCount()为1 
    int getItemViewType(int position) 
    获得position项view的类型,可以的返回值有0到getViewTypeCount() – 1和IGNORE_ITEM_VIEW_TYPE 
    boolean isEmpty() 
    是否包含有数据 
    ListAdapter增加 
    boolean isEnabled(int position) 
    public boolean areAllItemsEnabled() 
    返回false表示item不可选,不可点击 
    SpinnerAdapter增加 
    public View getDropDownView(int position, View convertView, ViewGroup parent) 
    position项下拉菜单的view 
    3.3         ArrayAdapter 
    class ArrayAdapter<T> extends BaseAdapter implements Filterable 
    ArrayAdapter(Context context, int textViewResourceId) 
    ArrayAdapter(Context context, int textViewResourceId, T[] objects) 
    ArrayAdapter(Context context, int textViewResourceId, List<T> objects) 
    ArrayAdapter(Context context, int resource, int textViewResourceId) 
    ArrayAdapter(Context context, int resource, int textViewResourceId, T[] objects) 
    ArrayAdapter(Context context, int resource, int textViewResourceId, List<T> objects) 
    context 
    textViewResourceId 
    没有resource参数时:含有TextView 的layout文件资源ID,创建view时使用; 
    有resource参数时:layout文件中TextView的ID 
    resource 
    loyout文件资源ID 
    objects 
    ListView显示的对象 
    SDK自带的textViewResourceId对应的xml文件在cupcake\frameworks\base\core\res\res\layout 
    android.R.layout.simple_list_item_1 
    TextView 
    android.R.layout.simple_list_item_2 
    含有两个TextView的TwoLineListItem 
    android.R.layout. simple_expandable_list_item_1 
    TextView 
    android.R.layout. simple_expandable_list_item_2 
    含有两个TextView的TwoLineListItem 
    android.R.layout. simple_list_item_single_choice 
    CheckedTextView 
    android.R.layout. simple_list_item_multiple_choice 
    CheckedTextView 
    android.R.layout. simple_list_item_checked 
    CheckedTextView 
    void add(T object) 
    void insert(T object, int index) 
    void remove(T object) 
    void clear() 
    void notifyDataSetChanged() 
    void setNotifyOnChange(boolean notifyOnChange) 
    列表发生改变时是否自动调用notifyDataSetChanged(),设为false则需手动调用 
    Context getContext() 
    void setDropDownViewResource(int resource) 
    设置创建下拉菜单view需要的layout资源文件 
    static ArrayAdapter<CharSequence> createFromResource(Context context, 
                int textArrayResId, int textViewResId) 
    Filter getFilter() 
    3.4         SimpleAdapter 
    public class SimpleAdapter extends BaseAdapter implements Filterable 
    public SimpleAdapter(Context context, List<? extends Map<String, ?>> data, 
                int resource, String[] from, int[] to) 
    context 
    data 
    resource 
    Layout文件id 
    from 
    data中Map的key 
    to 
    生成itemView的id, to[]数组大小不能超过from []的大小 
    public void setDropDownViewResource(int resource) 
    设置创建下拉菜单view需要的layout资源文件 
    public ViewBinder getViewBinder() 
    public void setViewBinder(ViewBinder viewBinder) 
    public static interface ViewBinder { 
    boolean setViewValue(View view, Object data, String textRepresentation); 

    绑定数据到view 
    用setViewBinder(null)的方式取消绑定 
    public void setViewImage(ImageView v, int value) 
    public void setViewImage(ImageView v, String value) 
    public void setViewText(TextView v, String text) 
    public Filter getFilter() 
    3.5         SimpleCursorAdapter 
    public class SimpleCursorAdapter extends ResourceCursorAdapter 
    demo 
    aipDemos/com.example.android.view/List2.java 
    List2.java,List3.java,List7.java 
    菜单路径:API Demos/Views/Lists/ 
    public SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) 
    context 
    layout 

    Curor 
    from 
    to 
    public View newView(Context context, Cursor cursor, ViewGroup parent) 
    public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) 
    public ViewBinder getViewBinder() 
    public void setViewBinder(ViewBinder viewBinder) 
    public void setViewImage(ImageView v, String value) 
    public void setViewText(TextView v, String text) 
    public void bindView(View view, Context context, Cursor cursor) 
    public int getStringConversionColumn() 
    public void setStringConversionColumn(int stringConversionColumn) 
    设置获取from[stringConversionColumn]中数据 
    public CursorToStringConverter getCursorToStringConverter() 
    public void setCursorToStringConverter( 
    CursorToStringConverter cursorToStringConverter) 
    public static interface CursorToStringConverter { 
    CharSequence convertToString(Cursor cursor); 

    public CharSequence convertToString(Cursor cursor) 
    获取from[stringConversionColumn]中数据 
    public void changeCursor(Cursor c) 
    3.6         HeaderViewListAdapter 
    public class HeaderViewListAdapter implements WrapperListAdapter, Filterable 
    private ListAdapter mAdapter; 
    ArrayList<ListView.FixedViewInfo> mHeaderViewInfos; 
    ArrayList<ListView.FixedViewInfo> mFooterViewInfos; 
    public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos, 
    ArrayList<ListView.FixedViewInfo> footerViewInfos, 
    ListAdapter adapter) 
    headerViewInfos 
    footerViewInfos 
    adapter 
    public class FixedViewInfo { 
    public View view; 
    public Object data; 
    public boolean isSelectable; 

    public int getHeadersCount() 
    public int getFootersCount() 
    public int getCount() 
    Header,Footer,mAdapter总item数 
    public boolean isEmpty() 
    mAdapter是否为空 
    public boolean removeHeader(View v) 
    public boolean removeFooter(View v) 
    public boolean areAllItemsEnabled() 
    public ListAdapter getWrappedAdapter() 
    获取mAdapter 

    四、            AbsListView4.1         概述 
    定义 
    public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher, 
            ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener, 
            ViewTreeObserver.OnTouchModeChangeListener 
    包路径 
    import android.widget.AbsListView; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsListView 
                         |___ GridView 
                         |___ ListView 
                                |___ ExpandableListView 
    4.2         部分方法 
    void setStackFromBottom(boolean stackFromBottom) 
    boolean isStackFromBottom() 
    单列 
    多列 
    Disable 
    Enable 
    Disable 
    Enable 














    void setScrollingCacheEnabled(boolean enabled) 
    boolean isScrollingCacheEnabled() 
    设置是否缓存卷动项,缓存则需额外的内存,缺省为enable 
    void setCacheColorHint(int color) 
    int getCacheColorHint() 
    int getSolidColor() 
    缓存项背景颜色 
    int pointToPosition(int x, int y) 
    返回包含坐标(x, y)的项,没有项包含该点则返回INVALID_POSITION 
    long pointToRowId(int x, int y) 
    void setTranscriptMode(int mode) 
    int getTranscriptMode() 
    TRANSCRIPT_MODE_DISABLED 
    当数据发生变化不自动滚动 
    TRANSCRIPT_MODE_NORMAL 
    当数据发生变化时,最后一项正显示在屏幕上,自动滚动到最低端 
    TRANSCRIPT_MODE_ALWAYS_SCROLL 
    当数据发生变化时,自动滚动到最低端 
    void setFilterText(String filterText) 
    void clearTextFilter() 
    boolean hasTextFilter() 
    过滤文本 
    void getFocusedRect(Rect r) 
    获取焦点框区域 
    View getSelectedView() 
    void setSelector(int resID) 
    void setSelector(Drawable sel) 
    Drawable getSelector() 
    焦点框 
    void setDrawSelectorOnTop(boolean onTop) 
    true:Selector绘制在文字之上 
    void setScrollIndicators(View up, View down) 
    void reclaimViews(List<View> views) 
    void setRecyclerListener(RecyclerListener listener) 
    LayoutParams generateLayoutParams(AttributeSet attrs) 
    void beforeTextChanged(CharSequence s, int start, int count, int after) 
    void onTextChanged(CharSequence s, int start, int before, int count) 
    void afterTextChanged(Editable s) 

    五、            ListView5.1         概述 
    定义 
    public class ListView extends AbsListView 
    包路径 
    import android.widget.ListView 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsListView 
                         |___ ListView 
                                |___ ExpandableListView 
    ListView显示为垂直可滚动的一列,所有item由ListAdapter提供。 
    5.2         部分方法 
    public ListView(Context context) 
    public ListView(Context context, AttributeSet attrs) 
    public ListView(Context context, AttributeSet attrs, int defStyle) 
    ListAdapter getAdapter() 
    void setAdapter(ListAdapter adapter) 
    设置listitem,adapter包含每一个item的数据并提供显示数据的view 
    void addHeaderView(View v, Object data, boolean isSelectable) 
    void addHeaderView(View v) 
    在list顶端加headView,可以加多个,按添加的顺序显示。isSelectable为可否被选择。 
    必须在setAdapter()前调用,否则抛出IllegalStateException异常 
    int getHeaderViewsCount() 
    获得headerView的数量 
    boolean removeHeaderView(View v) 
    必须在setAdapter()后调用,否则抛出NullPointerException异常(运行期异常)。 
    void addFooterView(View v, Object data, boolean isSelectable) 
    void addFooterView(View v) 
    在list尾添加footerView,同addHeaderView() 
    必须在setAdapter()前后调用都可以 
    int getFooterViewsCount() 
    获得footerView的数量 
    boolean removeFooterView(View v) 
    必须在setAdapter()后调用,否则抛出NullPointerException异常(运行期异常)。 
    int getChoiceMode() 
    void setChoiceMode(int choiceMode) 
    ListView. CHOICE_MODE_NONE 
    ListView. CHOICE_MODE_SINGLE 
    ListView. CHOICE_MODE_MULTIPLE 
    void setSelection(int position) 
    设置第position为选择状态 
    void setSelectionFromTop(int position, int y) 
    设置第position为选择状态,使position那项的位置在距离ListView顶端y的位置 
    void setSelectionAfterHeaderView() 
    使选择项位置紧挨着HeaderView。 
    void setItemsCanFocus(boolean itemsCanFocus) 
    boolean getItemsCanFocus() 
    Drawable getDivider() 
    void setDivider(Drawable divider) 
    设置每两个item间的分割 
    int getDividerHeight() 
    void setDividerHeight(int height) 
    设置每两个item间空隙的高度 
    boolean isItemChecked(int position) 
    在单选或多选状态下判断第position项状态 
    int getCheckedItemPosition() 
    在单选状态下获取选择的那项,多选无效 
    SparseBooleanArray getCheckedItemPositions() 
    非单选模式下有效 
    void clearChoices() 
    清除选择 
    void setItemChecked(int position, boolean value) 
    设置position项的状态 
    Parcelable onSaveInstanceState() 
    void onRestoreInstanceState(Parcelable state) 
    boolean performItemClick(View view, int position, long id) 
    boolean onTouchEvent(MotionEvent ev) 
    boolean dispatchKeyEvent(KeyEvent event) 
    boolean onKeyDown(int keyCode, KeyEvent event) 
    boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) 
    onKeyUp(int keyCode, KeyEvent event) 

    六、            ExpandableListView6.1         概述 
    定义 
    public class ExpandableListView extends ListView 
    包路径 
    import android.widget.ExpandableListView; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsListView 
                         |___ ListView 
                                |___ ExpandableListView 
    ExpandableListView显示为垂直可滚动的一列,与ListView的区别是它的item分group和child两层,item的children可以展开显示,也可以叠起不显示。所有item由ExpandableListAdapter提供。 
    ExpandableListItem的展开与否可以用setChildIndicator()或setGroupIndicator()来设置。 
    注意:如果ExpandableListView的parent高度设为WRAP_CONTENT,则不能指定ExpandableListView的layout_height为WRAP_CONTENT;如果parent高度一定则可以设为WRAP_CONTENT。 
    6.2         部分方法 
    void setAdapter(ListAdapter adapter) 
    抛出异常RuntimeException 
    ListAdapter getAdapter() 
    只获取groupList 
    void setAdapter(ExpandableListAdapter adapter) 
    ExpandableListAdapter getExpandableListAdapter() 
    设置ExpandableListView数据 
    boolean collapseGroup(int groupPos) 
    合上groupPosition组, 
    boolean expandGroup(int groupPos) 
    展开groupPosition组,是展开状态返回true 
    boolean isGroupExpanded(int groupPosition) 
    long getExpandableListPosition(int flatListPosition) 
    转换一个ListView的position(flatListPosition)为ExpandableList的packedPosition,packedPosition由ExpandableList的groupPosition和childPosition计算而来。 
    int getFlatListPosition(long packedPosition) 
    packedPosition转换为flatListPosition, 
    packedPosition类型为group时packedPosition跟groupPosition相等 
    packedPosition类型为child时packedPosition跟child所在的group的groupPosition相等 
    static int getPackedPositionType(long packedPosition) 
    packedPosition的类型,groupPosition还是childPosition 
    ExpandableListView.PACKED_POSITION_TYPE_GROUP 
    ExpandableListView.PACKED_POSITION_TYPE_CHILD 
    ExpandableListView.PACKED_POSITION_TYPE_NULL 
    static int getPackedPositionGroup(long packedPosition) 
    返回groupPosition 
    static int getPackedPositionChild(long packedPosition) 
    如果packedPosition的类型是PACKED_POSITION_TYPE_CHILD,返回childPosition 
    static long getPackedPositionForChild(int groupPosition, int childPosition) 
    生成child的packedPosition 
    static long getPackedPositionForGroup(int groupPosition) 
    生成group的packedPosition 
    long getSelectedPosition() 
    long getSelectedId() 
    void setGroupIndicator(Drawable groupIndicator) 
    groupItem的标识 
    void setIndicatorBounds(int left, int right) 
    groupItem标识的位置 
    void setChildIndicator(Drawable childIndicator) 
    childItem的标识 
    void setChildIndicatorBounds(int left, int right) 
    childItem标识的位置,从left开始到right结束,right>left才显示出来 
    left,right都可以指定ExpandableListView.CHILD_INDICATOR_INHERIT,继承groupItem表识的位置,即通过setIndicatorBounds()设置的位置 
    void setChildDivider(Drawable childDivider) 
    void setSelectedGroup(int groupPosition) 
    boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) 
    public void setOnChildClickListener(OnChildClickListener onChildClickListener) 
    设置childItem点击监听器 
    public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener) 
    设置groupItem点击监听器 
    public void setOnGroupCollapseListener ( 
    OnGroupCollapseListener onGroupCollapseListener) 
    设置groupItem合上时触发的监听器 
    public void setOnGroupExpandListener ( 
                       OnGroupExpandListener onGroupExpandListener) 
    设置groupItem展开时触发的监听器 
    public void setOnItemClickListener(OnItemClickListener l) 
    触发ItemClick的itemPos是flatListPosition,尽量用setOnChildClickListener()和setOnGroupClickListener()代替这个方法。 
    6.3         ExpandableListAdapter 
    BaseExpandableListAdapter 
    CursorTreeAdapter 
    SimpleExpandableListAdapter 
    ResourceCursorTreeAdapter 
    ExpandableListAdapter 
    SimpleCursorTreeAdapter 
    黑色文字为接口红色文字为类斜体字为抽象类 

    6.4         SimpleExpandableListAdapter 
    public class SimpleExpandableListAdapter extends BaseExpandableListAdapter 
    public SimpleExpandableListAdapter(Context context, 
                List<? extends Map<String, ?>> groupData, int groupLayout, 
                String[] groupFrom, int[] groupTo, 
                List<? extends List<? extends Map<String, ?>>> childData, 
                int childLayout, String[] childFrom, int[] childTo) 
    public SimpleExpandableListAdapter(Context context, 
                List<? extends Map<String, ?>> groupData, int expandedGroupLayout, 
                int collapsedGroupLayout, String[] groupFrom, int[] groupTo, 
                List<? extends List<? extends Map<String, ?>>> childData, 
                int childLayout, String[] childFrom, int[] childTo) 
    public SimpleExpandableListAdapter(Context context, 
                List<? extends Map<String, ?>> groupData, int expandedGroupLayout, 
                int collapsedGroupLayout, String[] groupFrom, int[] groupTo, 
                List<? extends List<? extends Map<String, ?>>> childData, 
                int childLayout, int lastChildLayout, String[] childFrom, 
                int[] childTo) 
    groupData 
    grouplist数据 
    groupLayout 
    grouplist loyout资源文件 
    expandedGroupLayout 
    grouplist 
    collapsedGroupLayout 
    grouplist 
    groupFrom 
    抽取groupData的Map的哪几列数据 
    groupTo 
    由groupFrom获取的数据生成view的viewId 
    childData 
    childlist数据 
    childLayout 
    childlistloyout资源文件 
    lastChildLayout 
    childFrom 
    抽取childlist的Map的哪几列数据 
    childTo 
    由childFrom获取的数据生成view的viewId 
    public int getChildrenCount(int groupPosition) 
    public Object getChild(int groupPosition, int childPosition) 
    public long getChildId(int groupPosition, int childPosition) 
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, 
                View convertView, ViewGroup parent) 
    public View newChildView(boolean isLastChild, ViewGroup parent) 
    public int getGroupCount() 
    public Object getGroup(int groupPosition) 
    public long getGroupId(int groupPosition) 
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, 
                ViewGroup parent) 
    public View newGroupView(boolean isExpanded, ViewGroup parent) 
    public boolean isChildSelectable(int groupPosition, int childPosition) 
    public boolean hasStableIds() 
    6.5         SimpleCursorTreeAdapter 
    public abstract class SimpleCursorTreeAdapter extends ResourceCursorTreeAdapter 
    public SimpleCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, 
                int expandedGroupLayout, String[] groupFrom, int[] groupTo, int childLayout, 
                int lastChildLayout, String[] childFrom, int[] childTo) 
    public SimpleCursorTreeAdapter(Context context, Cursor cursor, int collapsedGroupLayout, 
                int expandedGroupLayout, String[] groupFrom, int[] groupTo, 
                int childLayout, String[] childFrom, int[] childTo) 
    public SimpleCursorTreeAdapter(Context context, Cursor cursor, int groupLayout, 
                String[] groupFrom, int[] groupTo, int childLayout, String[] childFrom, 
                int[] childTo) 
    与SimpleExpandableListAdapter不同的是List<? extends Map<String, ?>> groupData改为Cursor cursor,共有方法都类似。 

    七、            ListActivity7.1         概述 
    定义 
    public class ListActivity extends Activity 
    包路径 
    import android.app.ListActivity 
    子类信息 
    Context 
    |___ ContextWrapper 
           |___ ContextThemeWrapper 
                  |___ Activity 
                         |___ ListActivity 
    继承Activity,封装一个ListView成员 
    demo 
    aipDemos/com.example.android.view/List1.java 
    List1.java ~ List14.java 
    菜单路径:API Demos/Views/Lists/ 
    7.2         部分方法 
    public void onContentChanged() 
    public void setListAdapter(ListAdapter adapter) 
    public ListAdapter getListAdapter() 
    public void setSelection(int position) 
    public int getSelectedItemPosition() 
    public long getSelectedItemId() 
    public ListView getListView() 
    获取ListView对象,可以使用ListView的方法 
    7.3         ExpandableListActivity 
    public class ExpandableListActivity extends Activity implements 
            OnCreateContextMenuListener, 
    ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, 
            ExpandableListView.OnGroupExpandListener 
    继承Activity封装一个ExpandableListView对象 

    八、            GridView8.1         概述 
    定义 
    public class GridView extends AbsListView 
    包路径 
    import android.widget.AbsListView 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsListView 
                         |___ GridView 
    多行多列可垂直方向滚动,只支持先行后列垂直方向滚动的模式;不支持先列后行水平方向滚动的模式 
    支持 
    不支持 
    1  2  3 
    4  5  6 

    1  4  7 
    2  5 
    3  6 
    demo 
    aipDemos/com.example.android.view/Grid1.java 
    Grid1.java ~ Grid2.java 
    菜单路径:API Demos/Views/Grid/ 
    8.2         部分方法 
    top padding 
    bottom padding 
    left padding 
    right padding 
    vertical spacing 
    horizontal spacing 

    void setVerticalSpacing(int verticalSpacing); 
    设置垂直方向行间距 
    void setHorizontalSpacing(int horizontalSpacing); 
    设置水平方向列间距 
    void setColumnWidth(int columnWidth); 
    设置列宽 
    void setNumColumns(int numColumns); 
    设置列数 
    void setGravity(int gravity); 
    设置item对齐方式 
    Gravity.TOP 
    Gravity.BOTTOM 
    Gravity.LEFT 
    缺省 
    Gravity.RIGHT 
    Gravity.CENTER_VERTICAL 
    Gravity.CENTER_HORIZONTAL 
    Gravity.CENTER 
    Gravity.FILL_VERTICAL 
    Gravity.FILL_HORIZONTAL 
    Gravity.FILL 
    Gravity.CLIP_VERTICAL 
    Gravity.CLIP_HORIZONTAL 
    int getStretchMode() 
    void setStretchMode(int stretchMode) 
    设置填充GridView时的方式 
    GridView.NO_STRETCH 
    使用设置的列宽和列间距排版,无视GridView的宽度 
    GridView.STRETCH_SPACING 
    拉伸列间距,根据列宽、列数和GridView的宽度计算列间距。Item+Space+Item 
    GridView.STRETCH_SPACING_UNIFORM 
    拉伸列间距,计算方式与 
    GridView.STRETCH_SPACING不同。 
    Space+Item+Space+Item+Space 
    GridView.STRETCH_COLUMN_WIDTH 
    拉伸列宽,根据列间距、列数和GridView的宽度计算列宽。 
    ListAdapter getAdapter() 
    void setAdapter(ListAdapter adapter) 
    设置item列表 
    public void setSelection(int position) 

    九、            AbsSpinner9.1         概述 
    定义 
    public abstract class AbsSpinner extends AdapterView<SpinnerAdapter> 
    包路径 
    import android.widget.AbsSpinner; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsSpinner 
                         |___ Gallery 
                         |___ Spinner 
    9.2         部分方法 
    void setAdapter(SpinnerAdapter adapter) 
    SpinnerAdapter getAdapter() 
    void setSelection(int position, boolean animate) 
    void setSelection(int position) 
    int getCount() 
    int pointToPosition(int x, int y) 
    Parcelable onSaveInstanceState() 
    void onRestoreInstanceState(Parcelable state) 

    十、            Gallery10.1     概述 
    定义 
    public class Gallery extends AbsSpinner implements GestureDetector.OnGestureListener 
    包路径 
    import android.widget.Gallery; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsSpinner 
                         |___ Gallery 
    items水平方向滚动显示,滚动停止时选择项停在屏幕正中。 
    demo 
    aipDemos/com.example.android.view/Gallery1.java 
    Gallery1.java ~ Gallery2.java 
    菜单路径:API Demos/Views/Gallery/ 
    10.2     部分方法 
    void setCallbackDuringFling(boolean shouldCallback) 
    滑动过程中是否每项都调用getOnItemSelectedListener()注册的callback 
    false:最后选中的一项才调用callback 
    true:所有项都调用callback 
    void setAnimationDuration(int animationDurationMillis) 
    设置反弹回屏幕正中这部分的动画时间间隔,单位毫秒,缺省为400ms。 
    void setSpacing(int spacing) 
    设置两项之间的间距,缺省为0,单位象素 
    void setUnselectedAlpha(float unselectedAlpha) 
    设置未选中项的alpha值 0~1.0 

    十一、           Spinner11.1     概述 
    定义 
    public class Spinner extends AbsSpinner implements OnClickListener 
    包路径 
    import android.widget.Spinner; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AdapterView<T extends Adapter> 
                  |___ AbsSpinner 
                         |___ Spinner 
    在一个单行文本框中,同时只显示一个有序列表中的一个项,点击弹出一个下拉单选对话框,从中进行选择。 
    系统自带布局文件: 
    simple_spinner_dropdown_item.xml 
    simple_spinner_item.xml 
    demo 
    aipDemos/com.example.android.view/Spinner1.java 
    菜单路径:API Demos/Views/Spinner/ 
    11.2     部分方法 
    public int getBaseline() 
    public void setOnItemClickListener(OnItemClickListener l) 
    抛出异常RuntimeException 
    public boolean performClick() 
    弹出下拉对话框 
    public void onClick(DialogInterface dialog, int which) 
    public void setPrompt(CharSequence prompt) 
    public void setPromptId(int promptId) 
    public CharSequence getPrompt() 
    设置下拉菜单标题 

    十二、           LinearLayout12.1     概述 
    定义 
    public class LinearLayout extends ViewGroup 
    包路径 
    import android.widget.LinearLayout; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ LinearLayout 
                  |___ RadioGroup 
                  |___ TabWidget 
                  |___ TableLayout 
                  |___ TableRow 
                  |___ ZoomControls 
                  |___ NumberPicker 
    LinearLayout可以设置位水平的一行或垂直的一列,所有子元素按加入顺序排列,通过setOrientation()来设置行模式还是列模式,缺省为行模式。通过setGravity()设置对齐方式。 
    也可以对单个子元素制定weight,允许子元素填充屏幕上的剩余空间,剩余空间安指定的比例分配。 
    demo 
    aipDemos/com.example.android.view/linear_layout_1.java 
    linear_layout_1.java ~ linear_layout_10.java 
    菜单路径:API Demos/Views/ Layouts/LinearLayout/ 
    12.2     部分方法 
    public LinearLayout(Context context) 
    public LinearLayout(Context context, AttributeSet attrs) 
    public boolean isBaselineAligned() 
    public void setBaselineAligned(boolean baselineAligned) 
    public int getBaseline() 
    获取baseline距离顶端的距离,不支持baseline对齐返回-1 
    public int getBaselineAlignedChildIndex() 
    public void setBaselineAlignedChildIndex(int i) 
    public float getWeightSum() 
    public void setWeightSum(float weightSum) 
    public void setOrientation(int orientation) 
    public int getOrientation() 
    HORIZONTAL:行模式 
    VERTICAL:列模式 
    public void setGravity(int gravity) 
    public void setHorizontalGravity(int horizontalGravity) 
    public void setVerticalGravity(int verticalGravity) 
    对齐方式 
    public LayoutParams generateLayoutParams(AttributeSet attrs) 
    public static class LayoutParams extends ViewGroup.MarginLayoutParams 
    增加了一个参数weight 
    public LayoutParams(int width, int height, float weight) 
    比如3个layout排成一行,分别为ly1, ly2, ly3 
    width值分别为width1,width2,width3 
    FILL_PARENT的宽度为WIDTH 
    weight值分别为weight1, weight2, weight3 
    只要weight1,weight2,weight3不同时为0,则3个layout总宽度变为WIDTH 
    ly1的宽度为 
    对weight未负数,width1+width2+width3 >= WIDTH未做测试 
    12.3     LinearLayout.LayoutParams 
    public static class LayoutParams extends ViewGroup.MarginLayoutParams 
    public float weight;              //增加weight属性 
    public int gravity = -1; 
    public LayoutParams(int width, int height, float weight) 
    12.4     RadioGroup 
    demo 
    aipDemos/com.example.android.view/RadioGroup1.java 
    菜单路径:API Demos/Views/ Radio Group/ 
    一列RadioButton 
    public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) 
    子项有变化时触发的监听器,增加/删除项 
    public void check(int id) 
    设置id项为选择 
    public int getCheckedRadioButtonId() 
    获取选择项的id 
    public void clearCheck() 
    清除选择状态 
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) 
    RadioButton状态改变监听器 
    12.5     TabWidget 
    通常用作TabHost的子元素,单独使用同LinearLayout。 
    12.6     TableRow 
    通常用作TableLayout子元素,单独使用同LinearLayout。 
    12.7     ZoomControls 
    系统带布局文件 
    zoom_controls.xml 
    public void setOnZoomInClickListener(OnClickListener listener) 
    public void setOnZoomOutClickListener(OnClickListener listener) 
    public void setZoomSpeed(long speed) 
    public boolean onTouchEvent(MotionEvent event) 
    public void show() 
    淡入 
    public void hide() 
    淡出消失 
    public void setIsZoomInEnabled(boolean isEnabled) 
    public void setIsZoomOutEnabled(boolean isEnabled) 
    public boolean hasFocus() 

    十三、           TableLayout13.1     概述 
    定义 
    public class TableLayout extends LinearLayout 
    包路径 
    import android.widget.TableLayout; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ LinearLayout 
                  |___ TableLayout 
    TableLayout将子元素的位置分配到行或列中,一个TableLayout由许多TableRow组成,每个TableRow都定义一个row,TableLayout不显示row、column或cell的边框线,每个row拥有0个或多个cell,每个cell拥有一个view对象。列可以被隐藏setColumnCollapsed(),也可以设置为伸展从而填充可利用的屏幕空间setColumnStretchable(),也可以设置为强制收缩直到表各匹配屏幕大小setColumnShrikable()。 
    TableLayout宽始终为FILL_PARENT,TableRow的高始终未WRAP_CONTEN。 
    demo 
    aipDemos/com.example.android.view/TableLayout1.java 
    TableLayout1.java ~ TableLayout12.java 
    菜单路径:API Demos/Views/ Layouts/TableLayout 
    13.2     部分方法 
    public boolean isShrinkAllColumns() 
    public void setShrinkAllColumns(boolean shrinkAllColumns) 
    是否所有列可收缩 
    public boolean isStretchAllColumns() 
    public void setStretchAllColumns(boolean stretchAllColumns) 
    是否所有列可拉伸 
    public void setColumnCollapsed(int columnIndex, boolean isCollapsed) 
    public boolean isColumnCollapsed(int columnIndex) 
    columnIndex列是否隐藏,必须是TableRow的列才能隐藏 
    public void setColumnStretchable(int columnIndex, boolean isStretchable) 
    public boolean isColumnStretchable(int columnIndex) 
    columnIndex列是否可拉伸 
    public void setColumnShrinkable(int columnIndex, boolean isShrinkable) 
    public boolean isColumnShrinkable(int columnIndex) 
    columnIndex列是否可收缩 
    13.3     TableLayout.LayoutParams 
    public static class LayoutParams extends LinearLayout.LayoutParams 
    重载了构造函数强制设width为FILL_PARENT 
    13.4     TableRow.LayoutParams 
    public static class LayoutParams extends LinearLayout.LayoutParams 
    public int column;  //第几列 
    public int span;      //占几列宽 
    public LayoutParams(int column) 

    十四、           FrameLayout14.1     概述 
    定义 
    public class FrameLayout extends ViewGroup 
    包路径 
    import android.widget.FrameLayout 
    子类信息 
    View 
    |___ ViewGroup 
           |___ FrameLayout 
                  |___ DatePicker 
                  |___ TimePicker 
                  |___ MediaController 
                  |___ ScrollView 
                  |___ TabHost 
                  |___ ViewAnimator 
                         |___ ViewFlipper 
                         |___ ViewSwitcher 
                                |___ ImageSwitcher 
                                |___ TextSwitcher 
    FrameLayout定制为屏幕上一个空白备用区域,可以在其中填充一个单一对象。所有的子元素将会固定在屏幕的左上角,不能为FrameLayout中一个子元素制定位置,后一个子元素将直接在前一个子元素之上进行覆盖填充,把他们全部或部分挡住(除非后一个子元素是透明的)。 
    14.2     部分方法 
    public FrameLayout(Context context) 
    public FrameLayout(Context context, AttributeSet attrs) 
    public FrameLayout(Context context, AttributeSet attrs, int defStyle) 
    public void setForegroundGravity(int foregroundGravity) 
    设置前景对齐方式,缺省为Gravity.FILL 
    public Drawable getForeground() 
    public void setForeground(Drawable drawable) 
    设置drawable,drawable是一个可绘制的“设备”,drawable显示在所有child之上 
    public void draw(Canvas canvas) 
    手动把canvas所在的view显示出来,不用重载该函数,注意与onDraw(Canvas)的区别 
    public boolean gatherTransparentRegion(Region region) 
    public void setMeasureAllChildren(boolean measureAll) 
    public boolean getConsiderGoneChildrenWhenMeasuring() 
    public LayoutParams generateLayoutParams(AttributeSet attrs) 
    14.3     FrameLayout. LayoutParams 
    public static class LayoutParams extends MarginLayoutParams 
    public int gravity = -1; 
    public LayoutParams(Context c, AttributeSet attrs) 
    public LayoutParams(int width, int height) 
    14.4     DatePicker 
    由3个NumberPicker组成,系统自带一个layout文件: 
    \cupcake\frameworks\base\core\res\res\layout\date_picker.xml, 
    这个缺省布局方式为水平LinearLayout,顺序为Month/Day/Year 
    这个控件dayOfMont的范围校验做的还不好,比如当前时间是2009/3/31,月份减一后为2009/2/31,而这个日期是非法的,但设置为系统日期是可以成功的,结果为2009/3/3。 
    demo 
    aipDemos/com.example.android.view/DateWidgets1.java 
    DateWidgets1.java ~ DateWidgets2.java 
    菜单路径:API Demos/Views/Date Widgets/ 
    public void setEnabled(boolean enabled) 
    public void updateDate(int year, int monthOfYear, int dayOfMonth) 
    monthOfYear:0~11 
    year:1900~2100 
    dayOfMonth:1~31 
    public void init(int year, int monthOfYear, int dayOfMonth, 
                OnDateChangedListener onDateChangedListener) 
    public void setEnabled(boolean enabled) 
    public int getYear() 
    public int getMonth() 
    public int getDayOfMonth() 
    14.5     TimePicker 
    demo同上 
    public void setEnabled(boolean enabled) 
    public void setOnTimeChangedListener( 
    OnTimeChangedListener onTimeChangedListener) 
    public Integer getCurrentHour() 
    public void setCurrentHour(Integer currentHour) 
    public void setIs24HourView(Boolean is24HourView) 
    public boolean is24HourView() 
    public Integer getCurrentMinute() 
    public void setCurrentMinute(Integer currentMinute) 
    public int getBaseline() 
    14.6     MediaController 
    demo 
    aipDemos/com.example.android.media/VideoViewDemo.java 
    14.7     ScrollView 
    demo 
    aipDemos/com.example.android.view/ScrollView1.java 
    ScrollView1.java ~ ScrollView2.java 
    aipDemos/com.example.android.view/InternalSelectionScroll.java 
    菜单路径:API Demos/Views/ Layouts/ScrollView/ 
    ScrollView只支持垂直方向滚动,只能有一个子对象,这个子对象的大小可以超过屏幕大小。这个子对象不能是ListView或TextView,因这两个view是自己管理如何滚动。这个子对象通常使用LinearLayout 
    public void addView(View child) 
    public void addView(View child, int index) 
    public void addView(View child, ViewGroup.LayoutParams params) 
    public void addView(View child, int index, ViewGroup.LayoutParams params) 
    只能有一个子元素,在已有一个子元素时再调用会抛出异常IllegalStateException() 
    public int getMaxScrollAmount() 
    public boolean isFillViewport() 
    public void setFillViewport(boolean fillViewport) 
    true:拉伸高度到viewport的高 
    public boolean isSmoothScrollingEnabled() 
    public void setSmoothScrollingEnabled(boolean smoothScrollingEnabled) 
    true:滚动过程用动画过渡 
    public boolean pageScroll(int direction) 
    翻页 
    public boolean fullScroll(int direction) 
    翻到底部或顶部 
    public boolean arrowScroll(int direction) 
    翻项 
    View.FOCUS_DOWN 
    View.FOCUS_UP 
    public final void smoothScrollBy(int dx, int dy) 
    相对目前位置滚动(x, y) 
    public final void smoothScrollTo(int x, int y) 
    滚动到绝对位置(x, y) 
    public void scrollTo(int x, int y) 
    无动画效果滚动 
    public void fling(int velocityY) 
    14.8     TabHost 
    demo 
    aipDemos/com.example.android.view/Tabs1.java 
    Tabs1.java~ Tabs3.java 
    菜单路径:API Demos/Views/ Layouts/LinearLayout/ 
    对应TabActivity 
    TabHost由TabWidget,TabContent组成。 
    TabWidget包含多个TabSpec;TabContent是FrameLayout. 
    TabSpec由tag,indictor,content组成,content可以是 
    1.ViewId;2.intent;3.TabHost.TabContentFactory。 
    内部接口TabHost.TabContentFactory 
    public interface TabContentFactory { 
    View createTabContent(String tag); 

    在xml文件中定义TabHost需注意两点: 
    1.TabWidget的id必须指定为"@android:id/tabs",否则会有RuntimeException 
    <TabWidget android:id="@android:id/tabs"/> 
    2.addTab()之前需调用setup()方法,继承TabActivity则不需要 
    public TabSpec newTabSpec(String tag) 
    创建一个tab标签,tab标签由3部分组成:tag文字,label文字/图片,content 
    内部类TabHost.TabSpec,它的每个函数都返回this对象,便于链式表达,比如: 
    tabHost.addTab(tabHost.newTabSpec("tab1") 
                    .setIndicator("tab1") 
                    .setContent(R.id.view1)); 
    public class TabSpec { 
    public TabSpec setIndicator(CharSequence label); 
    public TabSpec setIndicator(CharSequence label, Drawable icon); 
    public TabSpec setContent(int viewId); 
    public TabSpec setContent(TabContentFactory contentFactory); 
    public TabSpec setContent(Intent intent); 
    }; 
    public void setup() 
    public void setup(LocalActivityManager activityGroup) 
    从xml创建TabHost 才须调setup(),如果TabSpec的content是intent需调用带参数的setup() 
    public void addTab(TabSpec tabSpec) 
    public void clearAllTabs() 
    public void setCurrentTabByTag(String tag) 
    public void setCurrentTab(int index) 
    public int getCurrentTab() 
    public String getCurrentTabTag() 
    public View getCurrentTabView() 
    public View getCurrentView() 
    public TabWidget getTabWidget() 
    public FrameLayout getTabContentView() 
    public void onTouchModeChanged(boolean isInTouchMode) 
    public void setOnTabChangedListener(OnTabChangeListener l) 
    标签变化触发的监听器 
    14.9     ViewAnimator 
    因FrameLayout是多个子元素占同样的显示区域,则在不同子元素切换显示时可以加动画效果。通常是当前显示的view消失,下一个显示的view出现。 
    public void setDisplayedChild(int whichChild) 
    public void setDisplayedChild(int whichChild) 
    public int getDisplayedChild() 
    public void showNext() 
    public void showPrevious() 
    public void addView(View child, int index, ViewGroup.LayoutParams params) 
    重载了该方法,在加第一个view的状态为View.VISIBLE,之后加的view状态都是View.GONE 
    public View getCurrentView() 
    public Animation getInAnimation() 
    public void setInAnimation(Animation inAnimation) 
    public Animation getOutAnimation() 
    public void setOutAnimation(Animation outAnimation) 
    public void setInAnimation(Context context, int resourceID) 
    public void setOutAnimation(Context context, int resourceID) 
    public void setAnimateFirstView(boolean animate) 
    14.10 ViewFlipper 
    14.11 ViewSwitcher 
    14.12 ImageSwitcher 
    demo 
    aipDemos/com.example.android.view/ImageSwitcher1.java 
    菜单路径:API Demos/Views/ ImageSwitcher/ 
    14.13 TextSwitcher 
    demo 
    aipDemos/com.example.android.view/TextSwitcher1.java 
    菜单路径:API Demos/Views/ TextSwitcher/ 

    十五、           RelativeLayout15.1     概述 
    定义 
    public class RelativeLayout extends ViewGroup 
    包路径 
    import android.widget.RelativeLayout; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ RelativeLayout 
                  |___ DialerFilter 
                  |___ TwoLineListItem 
    RelativeLayout的child view位置可以用相对于其他元素或父元素的位置来描述。如果Y的位置依赖于X,则X需先于Y描述。 
    需要注意的是不要循环依赖,比如RelativeLayout的高设为WRAP_CONTENT,其child设为ALIGN_PARENT_BOTTOM 
    demo 
    aipDemos/com.example.android.view/RelativeLayout1.java 
    RelativeLayout1.java ~ RelativeLayout2.java 
    菜单路径:API Demos/Views/Layouts/RelativeLayout/ 
    15.2     部分方法 
    public void setIgnoreGravity(int viewId) 
    public void setGravity(int gravity) 
    public void setHorizontalGravity(int horizontalGravity) 
    public void setVerticalGravity(int verticalGravity) 
    public int getBaseline() 
    public LayoutParams generateLayoutParams(AttributeSet attrs) 
    public static class LayoutParams extends ViewGroup.MarginLayoutParams 
    LEFT_OF              位于指定child的左边 
    RIGHT_OF 
    ABOVE 
    BELOW 
    ALIGN_BASELINE      
    ALIGN_LEFT                     相对指定child的左边对齐 
    ALIGN_TOP 
    ALIGN_RIGHT 
    ALIGN_BOTTOM 
    ALIGN_PARENT_LEFT 
    ALIGN_PARENT_RIGHT 
    ALIGN_PARENT_TOP 
    ALIGN_PARENT_BOTTOM 
    CENTER_IN_PARENT 
    CENTER_HORIZONTAL 
    CENTER_VERTICAL 
    15.3     RelativeLayout.LayoutParams 
    public static class LayoutParams extends ViewGroup.MarginLayoutParams 
    public boolean alignWithParent;   
    public LayoutParams(Context c, AttributeSet attrs) 
    public LayoutParams(int w, int h) 
    public LayoutParams(ViewGroup.LayoutParams source) 
    public LayoutParams(ViewGroup.MarginLayoutParams source) 
    public void addRule(int verb) 
    只用于添加相对于parent的规则,可用addRule(verb, RelativeLayout.TRUE)代替,RelativeLayout.TRUE的值为-1 
    public void addRule(int verb, int anchor) 
    verb为相对于兄弟位置,则anchor必须为有效的兄弟id设置才生效,否则无效 
    verb为相对于parent位置,anchor无论设为何值都生效 
    public int[] getRules() 
    15.4     DialerFilter 
    15.5     TwoLineListItem 

    十六、           AbsoluteLayout16.1     概述 
    定义 
    public class AbsoluteLayout extends ViewGroup 
    包路径 
    import android.widget.Absolutelayout; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AbsoluteLayout 
                  |___ WebView 
    AbsoluteLayout可以对其子元素指定准确的x/y坐标值,允许元素之间相互重叠,不推荐使用。 
    16.2     部分方法 
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) 
    16.3     AbsoluteLayout. LayoutParams 
    public static class LayoutParams extends ViewGroup.LayoutParams 
    public int x;    // 在ViewGroup.LayoutParams基础上增加坐标(x, y) 
    public int y; 
    public LayoutParams(int width, int height, int x, int y) 
    public LayoutParams(Context c, AttributeSet attrs) 
    public LayoutParams(ViewGroup.LayoutParams source) 

    十七、           WebView17.1     概述 
    定义 
    public class WebView extends AbsoluteLayout 
            implements ViewTreeObserver.OnGlobalFocusChangeListener, 
            ViewGroup.OnHierarchyChangeListener 
    包路径 
    import android.webkit.WebView; 
    子类信息 
    View 
    |___ ViewGroup 
           |___ AbsoluteLayout 
                  |___ WebView 
    WebView用于显示网页,用于可滚动显示的web浏览器或简单显示在线内容的Activity。用WebKit显示网页和在历史记录向前向后操作、放大缩小、搜索文字 
    <uses-permission android:name="android.permission.INTERNET"/> 
    demo 
    aipDemos/com.example.android.view/webview_1.java 
    菜单路径:API Demos/Views/WebView/ 
    17.2     部分方法 
    public void clearCache(boolean includeDiskFiles) 
    public void goBack() 
    public void goForward() 
    public String getUrl() 
    public String getTitle() 
    public void reload() 
    public void loadUrl(String url) 
    public boolean zoomIn() 
    public boolean zoomOut() 

    public void goBackOrForward(int steps)



    转自:http://fly-ever.iteye.com/blog/1954411

    展开全文
  • ) : ViewGroup(context, attrs) { var horizontalSpacing: Int = 0 set(value) { field = value requestLayout() } var verticalSpacing: Int = 0 set(value) { field = value requestLayout() } init {...
  • 上面 是官方 给出的说明, 在调用draw()方法时,将会调用getChildDrawingOrder(int childCount ,int i)方法,ViewGroup 中默认是从上绘制到下,  如果有需要改变绘制的 先后的顺序,就可以从写改方法,...

     官方文档给出的 说明“

           

     protected int getChildDrawingOrder (int childCount, int i)

      返回迭代的绘制子类索引。如果你想改变子类的绘制顺序就要重写该方法。默认返回 i 值。

      提示:为了能够调用该方法,你必须首先调用setChildrenDrawingOrderEnabled(boolean)来允许子类排序。

      参数

           childCount        子类个数

      i        当前迭代顺序

      返回值

      绘制该迭代子类的索引

    上面 是官方 给出的说明, 在调用draw()方法时,将会调用getChildDrawingOrder(int childCount ,int i)方法,ViewGroup 中默认是从上绘制到下,

      如果有需要改变绘制的 先后的顺序,就可以从写改方法,(注意,我说的是顺序而不是位置

     在onmeasure,onLayout 方法中,位置和大小早就确定了, 所以说是不可能改变的。

     

        上面说明可能 不太明白,给出列子吧:

                                               


     如果看到上面 这样的 图,就知道是什么意思了,我想放大GridView中间的那个item,但是由于 gridview 是从上往下绘制,导致  下面的 item 覆盖在上面了,所以我们就得从写 getChildDrawingOrder(int childCount ,int i)这个方法

    改变绘制的顺序,


      @Override
         protected  int  getChildDrawingOrder( int  childCount,  int  i) {
             position = getSelectedItemPosition() - getFirstVisiblePosition();
             if (position< 0 ){
                 return  i;
             } else {
                 if (i == childCount -  1 ){ //这是最后一个需要刷新的item
                     if (position>i){
                         position=i;
                     }
                     return  position;
                 }
                 if (i == position){ //这是原本要在最后一个刷新的item
                     return  childCount -  1 ;
                 }
             }
             return  i;
         }

    由于是放大的那个是最后 需要绘制的,所以就不会出现这样的问题了



    展开全文
  • Android 自定义ViewGroup

    千次阅读 2014-04-09 22:04:41
    版本:1.0日期:2014.4.2版权:© 2014 kince 转载注明出处 之前介绍了关于自定义View类的一些知识,总结一下就是继承于View类,...实际开发中,用的不是很多,真正需求多的是像SliddingMenu侧滑菜单、下拉刷新等等。
  • 具体子View的测量模式和大小请看下表: 解决方法: View childView = View.inflate(this, R.layout.guideview_left, null);...//把子View添加到ViewGroup里面 mViewGroup.addView(childView , param);
  • 自定义Viewgroup 继承了FrameLayout 实现了下拉刷新,效果不错呦
  • Android适配任意View下拉刷新上拉加载,或上下弹性拽动的ViewGroup控件 http://blog.csdn.net/huanghuangjin/article/details/78244333
  • 主要为大家详细介绍了Android自定义viewgroup可滚动布局,GestureDetector手势监听,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • SwipeRefreshLayout是Android...SwipeRefreshLayout是继承自ViewGroup的,根据Android的事件分发机制,触摸事件应该是先传递到ViewGroup,根据onInterceptTouchEvent的返回值决定是否拦截事件的,那么就onInterceptT
  • 本文实例讲述了Android View刷新机制。分享给大家供大家参考,具体如下: 一、总体说明 在Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。 二、代码分析 1)....
  • 本篇文章讲的是Android 自定义ViewGroup之实现标签流式布局-FlowLayout,开发中我们会经常需要实现类似于热门标签等自动换行的流式布局的功能,网上也有很多这样的FlowLayout,但不影响我对其的学习。和往常一样,...
  • Android刷新布局

    千次阅读 2018-08-27 17:06:04
    学习安卓的高级技巧,其中的自定义View是必备课程。目前在研究该方面的东西,能用代码画出东西真令人兴奋! 以下是常见绘制后刷新布局的...如果是View就重绘View,如果是ViewGroup就全部重绘。 一般引起invalidat...
  • Android 下拉刷新框架实现

    万次阅读 多人点赞 2013-10-13 23:20:50
    一个通用的下拉刷新的框架介绍。 前段时间项目中用到了下拉刷新功能,之前在网上也找到过类似的demo,但这些demo的质量参差不齐,用户体验也不好,接口设计也不行。最张没办法,终于忍不了了,自己就写了一个下拉...
  • android开发中,总会避免不了用java代码动态设置控件宽高、边距等情况,而在使用ViewGroup.Params进行相关设置是各种类型的Params经常让人摸不到头脑,本文对Params进行简单总结,方便以后查找使用。
  • android_viewGroup详解

    万次阅读 2013-06-03 15:11:37
     来的的副作用:非常迅速的将View/ViewGroup偏移至目标点,而没有对这个偏移过程有任何控制,对用户而言可能是不太  友好的。于是,基于这种偏移控制,Scroller类被设计出来了,该类的主要作用是为偏移过程制定...
  • Android ViewPager刷新问题问题描述解决方法 问题描述 ViewPager的刷新机制和ListView不太一样,ListView中当调用Adapter的notifyDataSetChanged方法后会把列表所有itemView重新绘制一遍。ViewPager在初始化后会生成...
  • Android下拉刷新和上拉加载更多

    万次阅读 多人点赞 2018-01-31 11:06:29
    Android下拉刷新和上拉加载更多 下拉刷新 通过android系统提供的组件:SwipeRefreshLayout 一、基本使用 1 xml中 添加 SwipeRefreshLayout 组件 该组件包含着要操作下拉刷新的控件 如ListView RecyclerView...
  • 使用Refresh ListView 实现Android下拉刷新 翻译自http://www.androidhive.info/2015/05/android-swipe-down-to-refresh-listview-tutorial/ 你或许已经发现很多安卓应用,比如说Twitter,Google+提供了下拉刷新,...
  • Android PagerAdapter刷新当前显示布局

    千次阅读 2019-12-25 20:43:25
    Android PagerAdapter刷新布局显示PagerAdapter基本写法刷新布局 PagerAdapter基本写法 主要重写这四个方法,再将adapter设置到pageview中就可以显示可滑动的view了。 public class MyAdapter extends PagerAdapter ...
  • Android 下拉刷新控件 SwipeRefreshLayout

    千次阅读 2014-04-25 14:01:52
    上个月,google发布了自己的下拉刷新控件------SwipeRefreshLayout,该控件封装在android-support-v4.jar包中,依靠监听OnRefreshListener实现刷新操作。该控件用法十分简单,setEnable()方法控制刷新是否可用,...
  • androidViewGroup关于Layout的一点思考

    千次阅读 2012-09-02 01:30:09
    1、ViewGroup类继承与View,因此ViewGroup拥有View的一些特性,但是ViewGoup作为容器(LinearLayout,FrameLayout)的Base类,,也拥有一些View不具有的特性; 2、ViiewGroup下面可以拥有多个子View,每个子View的大小和...
  • Android知识梳理之自定义ViewGroup

    千次阅读 2016-04-27 14:12:16
    在我们进行android开发的时候虽然官方提供了...众所周知Android自定义为一般分为三类:自定义ViewGroup,自绘View,组合View。本篇将和大家一起探讨自定义ViewGrop 的相关知识. 转载请注明出处:http://blog.csd...
  • 今天要研究的是android v4自带的下拉刷新SwipeRefreshLayout,本来很久很久以前就想去研究一下它的,总是说自己没时间,其实时间挤挤还是有的,不废话了,先看一下最后用SwipeRefreshLayout实现的仿微信下拉刷新的...
  • Android View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。这就证明了一点,View代表了用户界面组件的一块可绘制的空间块。...
  • Android下拉刷新可扩展实现

    千次阅读 2013-06-25 20:45:11
    现在几乎所有的主流商业应用都支持某些...进行刷新的页面可以扩展到任何ViewGroup。最近在学习下拉刷新的实现,这个demo的UI效果和一些成熟APP是一致的,并有良好的可扩展性。  主要包含两个类,一个类是PullRefreshL

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,738
精华内容 9,895
热门标签
关键字:

androidviewgroup刷新