android 阶段总结1

  View.java     /**
     * <p>
     * This is called to find out how big a view should be. The parent
     * supplies constraint information in the width and height parameters.
     * </p>
     *
     * <p>
     * The actual mesurement work of a view is performed in
     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
     * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
     * </p>
     *
     *
     * @param widthMeasureSpec Horizontal space requirements as imposed by the
     *        parent
     * @param heightMeasureSpec Vertical space requirements as imposed by the
     *        parent
     *
     * @see #onMeasure(int, int)
     */
    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
                widthMeasureSpec != mOldWidthMeasureSpec ||
                heightMeasureSpec != mOldHeightMeasureSpec) {

            // first clears the measured dimension flag
            mPrivateFlags &= ~MEASURED_DIMENSION_SET;

            if (ViewDebug.TRACE_HIERARCHY) {
                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
            }

            // measure ourselves, this should set the measured dimension flag back
            onMeasure(widthMeasureSpec, heightMeasureSpec); //重点是它

            // flag not set, setMeasuredDimension() was not invoked, we raise
            // an exception to warn the developer
            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
                throw new IllegalStateException("onMeasure() did not set the"
                        + " measured dimension by calling"
                        + " setMeasuredDimension()");
            }

            mPrivateFlags |= LAYOUT_REQUIRED;
        }

        mOldWidthMeasureSpec = widthMeasureSpec;
        mOldHeightMeasureSpec = heightMeasureSpec;
    }



    /**
     * <p>
     * Measure the view and its content to determine the measured width and the
     * measured height. This method is invoked by {@link #measure(int, int)} and
     * should be overriden by subclasses to provide accurate and efficient
     * measurement of their contents.
     * </p>
     *
     * <p>
     * <strong>CONTRACT:</strong> When overriding this method, you
     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
     * measured width and height of this view. Failure to do so will trigger an
     * <code>IllegalStateException</code>, thrown by
     * {@link #measure(int, int)}. Calling the superclass'
     * {@link #onMeasure(int, int)} is a valid use.
     * </p>
     *
     * <p>
     * The base class implementation of measure defaults to the background size,
     * unless a larger size is allowed by the MeasureSpec. Subclasses should
     * override {@link #onMeasure(int, int)} to provide better measurements of
     * their content.
     * </p>
     *
     * <p>
     * If this method is overridden, it is the subclass's responsibility to make
     * sure the measured height and width are at least the view's minimum height
     * and width ({@link #getSuggestedMinimumHeight()} and
     * {@link #getSuggestedMinimumWidth()}).
     * </p>
     *
     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
     *                         The requirements are encoded with
     *                         {@link android.view.View.MeasureSpec}.
     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
     *                         The requirements are encoded with
     *                         {@link android.view.View.MeasureSpec}.
     *
     * @see #getMeasuredWidth()
     * @see #getMeasuredHeight()
     * @see #setMeasuredDimension(int, int)
     * @see #getSuggestedMinimumHeight()
     * @see #getSuggestedMinimumWidth()
     * @see android.view.View.MeasureSpec#getMode(int)
     * @see android.view.View.MeasureSpec#getSize(int)
     */
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        
              setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }



每个view 中一定存在一个必调的方法, measure(int, int) ,它调用onMeasure(int, int)
onMeasure(widthMeasureSpec, heightMeasureSpec)的作用是什么?
测量view和它的content 得出 widthMeasureSpec  heightMeasureSpec 并保存下来。
measure(widthMeasureSpec, heightMeasureSpec)的作用是什么?
通过 父布局提供的 widthMeasureSpec,   widthMeasureSpec 来确定这个View 的 大小, 有多高,有多宽,



特别对于一些实现 ViewGroup 的 控件 在某些情况下,当 android:layout_height android:layout_width 不能达到目的时, 可以通过重写 onMeasure(int, int) 来达到调整view高宽的目的。


    /**
     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
     * measured width and measured height. Failing to do so will trigger an
     * exception at measurement time.</p>
     *
     * @param measuredWidth The measured width of this view.  May be a complex
     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
     * {@link #MEASURED_STATE_TOO_SMALL}.
     * @param measuredHeight The measured height of this view.  May be a complex
     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
     * {@link #MEASURED_STATE_TOO_SMALL}.
     */
    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
        mMeasuredWidth = measuredWidth;
        mMeasuredHeight = measuredHeight;

        mPrivateFlags |= MEASURED_DIMENSION_SET;
    }

setMeasuredDimension 在 onMeasure(int, int) 中调用,用来存储跟新测量的宽和高, 若不调,可能产生异常。


MeasureSpec介绍及使用详解 
MeasureSpec 是 view 中的内部类
一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。一个MeasureSpec由大小和模式组成。它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;AT_MOST(至多),子元素至多达到指定大小的值。

1 父布局传下来的
2 子元素布局文件或代码中设置的

  它常用的三个函数:
  1.staticint getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
  2.staticint getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
  3.staticint makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)

  这个类的使用呢,通常在view组件的onMeasure方法里面调用但也有少数例外,看看几个例子:

  a.首先一个我们常用到的一个有用的函数,View.resolveSize(intsize,int measureSpec)


    public static int resolveSize(int size, int measureSpec) {
        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
    }

    public static int resolveSizeAndState(int size, int measureSpec, int childMe		asuredState) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize =  MeasureSpec.getSize(measureSpec);
        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        case MeasureSpec.AT_MOST:
            if (specSize < size) {
                result = specSize | MEASURED_STATE_TOO_SMALL;
            } else {
                result = size;
            }
            break;
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result | (childMeasuredState&MEASURED_STATE_MASK);
    }

  简单说一下,这个方法的主要作用就是根据你提供的大小和MeasureSpec,返回你想要的大小值,这个里面根据传入模式的不同来做相应的处理。
  再看看MeasureSpec.makeMeasureSpec方法,实际上这个方法很简单:
        public static int makeMeasureSpec(int size, int mode) {
            return size + mode;
        }
这样大家不难理解size跟measureSpec区别了。






******************************************

布局步骤
1 measure          onMeasure(measureWidth, measureHight)          计算大小
2 layout           onLayout(chang, l, t, r, b)   给自己 及 子view分配size, position
3 draw             ondraw(canvas)                 画图



dispatchDraw     空方法体





getWidth() getMeasureWidth() 区别
getWidth() : view 的布局完成后,view的宽度
getMeasureWidth() : 这是一个过程量,得到的是在最近一次調用measure()方法測量後得到的view的寬度,它僅僅用在測量和layout的計算中。
举例: 有时会通过 child.getMeasureWidth() 的值 根据 Gravity 重心 得出 view 的 4个l t r  b  再layout
如 Gridview 中 存在一个方法:
    private void setupChild(View child, int position, int y, boolean flow, int childrenLeft,
            boolean selected, boolean recycled, int where) {
        boolean isSelected = selected && shouldShowSelector();
        final boolean updateChildSelected = isSelected != child.isSelected();
        final int mode = mTouchMode;
        final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
                mMotionPosition == position;
        final boolean updateChildPressed = isPressed != child.isPressed();
        
        boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();

        // Respect layout params that are already in the view. Otherwise make
        // some up...
        AbsListView.LayoutParams p = (AbsListView.LayoutParams)child.getLayoutParams();
        if (p == null) {
            p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT, 0);
        }
        p.viewType = mAdapter.getItemViewType(position);

        if (recycled && !p.forceAdd) {
            attachViewToParent(child, where, p);
        } else {
            p.forceAdd = false;
            addViewInLayout(child, where, p, true);
        }

        if (updateChildSelected) {
            child.setSelected(isSelected);
            if (isSelected) {
                requestFocus();
            }
        }

        if (updateChildPressed) {
            child.setPressed(isPressed);
        }

        if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
            if (child instanceof Checkable) {
                ((Checkable) child).setChecked(mCheckStates.get(position));
            } else if (getContext().getApplicationInfo().targetSdkVersion
                    >= android.os.Build.VERSION_CODES.HONEYCOMB) {
                child.setActivated(mCheckStates.get(position));
            }
        }

        if (needToMeasure) {
            int childHeightSpec = ViewGroup.getChildMeasureSpec(
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);

            int childWidthSpec = ViewGroup.getChildMeasureSpec(
                    MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
            child.measure(childWidthSpec, childHeightSpec);
        } else {
            cleanupLayoutState(child);
        }

        final int w = child.getMeasuredWidth();
        final int h = child.getMeasuredHeight();

        int childLeft;
        final int childTop = flow ? y : y - h;

        final int layoutDirection = getResolvedLayoutDirection();
        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
            case Gravity.LEFT:
                childLeft = childrenLeft;
                break;
            case Gravity.CENTER_HORIZONTAL:
                childLeft = childrenLeft + ((mColumnWidth - w) / 2);
                break;
            case Gravity.RIGHT:
                childLeft = childrenLeft + mColumnWidth - w;
                break;
            default:
                childLeft = childrenLeft;
                break;
        }

        if (needToMeasure) {
            final int childRight = childLeft + w;
            final int childBottom = childTop + h;
            child.layout(childLeft, childTop, childRight, childBottom);
        } else {
            child.offsetLeftAndRight(childLeft - child.getLeft());
            child.offsetTopAndBottom(childTop - child.getTop());
        }

        if (mCachingStarted) {
            child.setDrawingCacheEnabled(true);
        }

        if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
                != position) {
            child.jumpDrawablesToCurrentState();
        }
    }









ViewGroup.java

 1  measureChildren(measureWidth, measureHight)    measureChild(child, widthMeasureSpec, heightMeasureSpec)

  2 继承 layout(l, t, r, b)      onLayout(chang, l, t, r, b)

  3 继承  dispatchDraw       drawChild


 window                         view      


                                        Window        抽象类
                                              |
                                    PhoneWindow        
                                               |
                                      DecorView(mDecor)       PhoneWindow 内部类, 继承FrameLayout
                                         |             |
                TextView(title)       ViewGroup(mParentContent)
                                                                           |
                                                                     ViewGroup
                                                    |         |              |
                                                View      View         ViewGroup
                                                                                            |       |      |
                                                                                      View    View    ViewGroup

                     Application     Part  main.xml




     window 与 view                                          
    Android系 统中的所有UI类都是建立在View和ViewGroup这两个类的基础上的。所有View的子类成为”Widget”,所有ViewGroup的子类成 为”Layout”。View和ViewGroup之间采用了组合设计模式,可以使得“部分-整体”同等对待。ViewGroup作为布局容器类的最上 层,布局容器里面又可以有View和ViewGroup。
  
   window 抽象类 代表 一个phone 界面。 在 里面有个 DecorView 类, DecorView 继承自
FrameLayout,   DecorView 是 window 与 view 链接的开始。 DecorView显示界面组件。
除此之外 window 中还定义了窗口的 基本属性 和 基本功能。
    Window 在继承关系上 与view 无关系。


   当我们运行程序的时候,有一个setContentView()方法,Activity其实不是显示视图(直观上感觉是它),实际上Activity调用 了PhoneWindow的setContentView()方法,然后加载视图,将视图放到这个Window上,而Activity其实构造的时候初始 化的是Window(PhoneWindow),Activity其实是个控制单元,即可视的人机交互界面。


其他 kan      app课件

<style type="text/css"> <!-- pre {font-family:"DejaVu Sans"} p {margin-bottom:0.21cm} --> </style>

webview
view 的 scrollbar 四种模式
SCROLLBARS_INSIDE_OVERLAY  without increasing the padding
SCROLLBARS_INSIDE_INSET        increasing the padding
SCROLLBARS_OUTSIDE_OVERLAY     without increasing the padding
SCROLLBARS_OUTSIDE_INSET    increasing the padding

boolean  mOverlayHorizontalScrollbar   表示是否水平方向 scrollbar overlay 模式   
boolean  mOverlayVerticalScrollbar     表示是否垂直方向 scrollbar overlay 模式 




isHorizontalScrollBarEnabled() 表示水平方向的 scrollbar 是否被画出。
GetHorizontalScrollbarHeight() 水平方向  scrollbar 高度。  View 里方法

    int getViewHeightWithTitle() {
        int height = getHeight();
        if (isHorizontalScrollBarEnabled() && !mOverlayHorizontalScrollbar) {
            height -= getHorizontalScrollbarHeight();
        }
        return height;
    }

 如果水平方向的 scrollbar 被画出且 属于 增加区域的 某种模式 计算viewHight时要减去这块区域的高。


    private boolean handleTouchEventCommon(MotionEvent ev, int action, int x, int y) {
        long eventTime = ev.getEventTime();

        // Due to the touch screen edge effect, a touch closer to the edge
        // always snapped to the edge. As getViewWidth() can be different from
        // getWidth() due to the scrollbar, adjusting the point to match
        // getViewWidth(). Same applied to the height.
        x = Math.min(x, getViewWidth() - 1);             
        y = Math.min(y, getViewHeightWithTitle() - 1);    

        int deltaX = mLastTouchX – x;         
        int deltaY = mLastTouchY - y;
        int contentX = viewToContentX(x + mScrollX);
        int contentY = viewToContentY(y + mScrollY);

x  x轴坐标      y y轴坐标      一台手机屏幕的宽高是固定的 (x,y) 手机屏幕
mLastTouchX  上一次触点的 x轴坐标
mLastTouchY 上一次触点的 y轴坐标
mScrollX  scrollbar 滑动 x轴距离
mScrollY  scrollbar 滑动 y轴距离
viewToContentX(.) webview content x轴坐标  网页+scrollbar
(contentx, contenty)  webview content 坐标

OverScroller

介绍
IOS上的bounce功能给人的感觉很爽,当一个可以滚动的区域被拖到边界时,它允许用户将内容拖过界,放手后再弹回来,以一种非常棒的方式提示 了用户边界的存在,是IOS的一大特色。android2.3新增了overscroll功能,听名字就知道应该是bounce功能的翻版,但也许是出于 专利方面的考虑,google的默认实现跟IOS有所不同,它只是在list拖到边界处时做了一个发光的动画,个人觉得体验比IOS差远了。而且这个黄色 的发光在黑色背景下虽然效果不错,在其它背景下可就难说了,因此很多人想要关掉它。
日前google上搜索“android overscroll”,对此效果的介绍很多,但关于其具体使用方式和实现,则很少涉及,偶有提及,也经常答非所问或似是而非,反而误导了别人。于是我查阅了android相关源码,并做了一些测试,在此讲讲我的理解。
首先是overscroll功能本身,在最顶层的View类提供了支持,可通过setOverScrollMode函数控制其出现条件。但其实 View中并没有实现overscroll功能,它仅仅提供了一个辅助函数overScrollBy,该函数根据overScrollMode和内容是否 需要滚动控制最大滚动范围,最后将计算结果传给onOverScrolled实现具体的overscroll功能,但此函数在View类中是全空的。
overscroll功能真正的实现分别在ScrollView、AbsListView、HorizontalScrollView和 WebView中各有一份,代码基本一样。以ScrollView为例,它在处理笔点移动消息时调用overScrollBy来滚动视图,然后重载了 overScrollBy函数来实现具体功能,其位置计算通过OverScroller类实现。OverScroller作为一个计算引擎,应该是一个独 立的模块,具体滚动效果和范围都不可能通过它来设置,我觉得没有必要细看。但滚动位置最终是它给出的,那相关数据肯定要传递给它,回头看 overScrollBy函数,它有两个控制overScroll出界范围的参数,几个实现里面都是取自 ViewConfiguration.getScaledOverscrollDistance,而这个参数的值在我的源码中都是0,而且我没找到任何可 以影响其结果的设置。
真悲催,绕了半天,android的默认实现里面根本没有给出overscroll功能,它只是提供了实现机制,要想用起来还得应用程序自己显式重写相关控件,估计还有一层隐含的意思,法律风险自负。在我的系统中一试,果然一个像素都不能拉出界。但那个闪光是怎么回事呢?
在处理笔点消息处,overScrollBy后面不远处有一段mEdgeGlowTop的操作代码,看名字就像,用它一搜,相关机制就全明白了。 mEdgeGlowTop在setOverScrollMode函数时创建,它使用的图片都是系统中固有的,甚至不能通过theme改变。它的实现原理也 很简单,仅仅是两张png图片的合成,通过透明度的变化制造闪光的效果。更无语的是它既不能被应用程序访问,也不受任何控制,要关闭它的唯一办法是 setOverScrollMode(View.OVER_SCROLL_NEVER)。否则就重写onTouchEvent函数吧,想干啥都可以,只是 得自己做。
谈到overScroll,很多文章都提到了ListView的setOverscrollHeader和 setOverscrollFooter,很多人想通过这个来控制那个闪光效果。这两玩意不但可以通过函数设置,也可以在xml中指定,相当方便。但最后 很多人发现没有任何作用,百思不得其解。其实这两张图片是用来作为overScroll拖过界时的背景的,默认系统不能拖过界,自然永远都看不到,有些定 制的系统中能拖出界几个像素,但也很难看清。

Boolean  AllowDoubleTap 允许双击 
    只有 onPageFinish() 后  AllowDoubleTap=true ,其他时候双击无效。

Int mTouchHighlightRequested set mTouchHighlightRequested to 0 to cause an 
  immediate  drawing of the touch rings  设为0, 区域立即开始高亮。
Region MtouchHighlightRegion = new Region() 代表一块区域,点击网页,产生高亮的区域.









页面可见坐标计算流程
  屏幕可见坐标 + view滚动条数据 + webview放缩数据


    /**
     * Given a distance in view space, convert it to content space. Note: this
     * does not reflect translation, just scaling, so this should not be called
     * with coordinates, but should be called for dimensions like width or
     * height.
     */
    private int viewToContentDimension(int d) {
        return Math.round(d * mZoomManager.getInvScale());
    }

    /**
     * Given an x coordinate in view space, convert it to content space.  Also
     * may be used for absolute heights (such as for the WebTextView's
     * textSize, which is unaffected by the height of the title bar).
     */
    /*package*/ int viewToContentX(int x) {  
        return viewToContendtDimension(x);     根据 webview 页面的放缩率  完善 Rect坐标
    }

    private Point mGlobalVisibleOffset = new Point();
    // Sets r to be the visible rectangle of our webview in view coordinates
    private void calcOurVisibleRect(Rect r) {   计算出 webview 可见区域坐标付给Rect
        getGlobalVisibleRect(r, mGlobalVisibleOffset);  计算手机屏幕的可见区域坐标付给Rect
        r.offset(-mGlobalVisibleOffset.x, -mGlobalVisibleOffset.y);  根据页面滚动条的数据如 scrollx scrolly 完善 Rect坐标。
    }

    private void calcOurContentVisibleRect(Rect r) {    传入Rect 对象
        calcOurVisibleRect(r);                 
        r.left = viewToContentX(r.left);
        // viewToContentY will remove the total height of the title bar.  Add
        // the visible height back in to account for the fact that if the title
        // bar is partially visible, the part of the visible rect which is
        // displaying our content is displaced by that amount.
        r.top = viewToContentY(r.top + getVisibleTitleHeightImpl());
        r.right = viewToContentX(r.right);
        r.bottom = viewToContentY(r.bottom);
    }


















webtextview 的尺寸 位置更新
    // These values are possible options for didUpdateWebTextViewDimensions.
    private static final int FULLY_ON_SCREEN = 0;
    private static final int INTERSECTS_SCREEN = 1;
    private static final int ANYWHERE = 2;

    /**
     * Check to see if the focused textfield/textarea is still on screen.  If it
     * is, update the the dimensions and location of WebTextView.  Otherwise,
     * remove the WebTextView.  Should be called when the zoom level changes.
     * @param intersection How to determine whether the textfield/textarea is
     *        still on screen.
     * @return boolean True if the textfield/textarea is still on screen and the
     *         dimensions/location of WebTextView have been updated.
     */
    private boolean didUpdateWebTextViewDimensions(int intersection) {
	    //计算出焦点坐标节点区域
        Rect contentBounds = nativeFocusCandidateNodeBounds();
        Rect vBox = contentToViewRect(contentBounds);
		 offsetByLayerScrollPosition(vBox);
	    //计算出可见区域
        Rect visibleRect = new Rect();
        calcOurVisibleRect(visibleRect);
        
        // If the textfield is on screen, place the WebTextView in
        // its new place, accounting for our new scroll/zoom values,
        // and adjust its textsize.
        boolean onScreen;
        switch (intersection) {
            case FULLY_ON_SCREEN:     vBox 在  visibleRect 之内
                onScreen = visibleRect.contains(vBox);
                break;
            case INTERSECTS_SCREEN:   vBox 与 visibleRect 交互
                onScreen = Rect.intersects(visibleRect, vBox);
                break;
            case ANYWHERE:            
                onScreen = true;
                break;
            default:
                throw new AssertionError(
                        "invalid parameter passed to didUpdateWebTextViewDimensions");
        }
        if (onScreen) {
            mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
                    vBox.height());
            mWebTextView.updateTextSize();
            updateWebTextViewPadding();  设置输入框内的padding,
            return true;
        } else {
            // The textfield is now off screen.  The user probably
            // was not zooming to see the textfield better.  Remove
            // the WebTextView.  If the user types a key, and the
            // textfield is still in focus, we will reconstruct
            // the WebTextView and scroll it back on screen.
            mWebTextView.remove();
            return false;
        }
    }


android 焦点控制
* 父元素分配焦点 

setFocusable()   设置view接受焦点的资格    isFocusable    view是否具有接受焦点的资格   

setFocusInTouchMode()      对应在触摸模式下,设置是否有焦点来响应点触的资格          
isFocusableInTouchMode()  对应在触摸模式下,来获知是否有焦点来响应点触

焦点获取
requestFocus()                                 ------ view
requestFocus(...)          当用户在某个界面聚集焦点
requestFocusFromTouch()    触摸模式下
  ......
requestChildFocus (View child, View focused)   ------viewGroup
1 父元素 调用此方法
2 child  将要获取焦点的子元素

3 focused 现在拥有焦点的子元素

一般也可以通过 配置文件设置
View.FOCUS_LEFT     Move focus to the left
View.FOCUS_UP       Move focus up
View.FOCUS_RIGHT    Move focus to the right
View.FOCUS_DOWN     Move focus down             代码设置实现 其实都是通过这些设置的         

isInTouchMode()    触摸模式


你可能感兴趣的:(android)