Android技术知识Android开发经验谈Android开发

setDescendantFocusability

2018-03-22  本文已影响366人  iSuperRed
努力学习.png

1 简介

setDescendantFocusability(int focusability)ViewGroup 的方法,其作用是设置 ViewGroup 的子View获取焦点的能力。

科普一下英文单词

descendant 
英[dɪˈsendənt]  美[dɪˈsɛndənt]  复数:[descendants] 

n. 后裔; 后代; (由过去类似物发展来的) 派生物; 弟子; 
adj.下降的; 祖传的; |

[例句]They are descendants of the original English and Scottish settlers.
他们是最初的英格兰和苏格兰定居者的后代。

2 实现

setDescendantFocusability(int focusability) 的具体实现代码如下所示:

/**
   * Set the descendant focusability of this view group. This defines the relationship
   * between this view group and its descendants when looking for a view to
   * take focus in {@link #requestFocus(int, android.graphics.Rect)}.
   *
   * @param focusability one of {@link #FOCUS_BEFORE_DESCENDANTS}, {@link #FOCUS_AFTER_DESCENDANTS},
   *   {@link #FOCUS_BLOCK_DESCENDANTS}.
   */
  public void setDescendantFocusability(int focusability) {
      switch (focusability) {
          case FOCUS_BEFORE_DESCENDANTS:
          case FOCUS_AFTER_DESCENDANTS:
          case FOCUS_BLOCK_DESCENDANTS:
              break;
          default:
              throw new IllegalArgumentException("must be one of FOCUS_BEFORE_DESCENDANTS, "
                      + "FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS");
      }
      mGroupFlags &= ~FLAG_MASK_FOCUSABILITY;
      mGroupFlags |= (focusability & FLAG_MASK_FOCUSABILITY);
  } 

setDescendantFocusability(int focusability) 方法可以传入的参数只有三种,
分别为:FOCUS_BEFORE_DESCENDANTSFOCUS_AFTER_DESCENDANTSFOCUS_BLOCK_DESCENDANTS ,从源码中也能看出来,除了这三种参数,传入其它参数会抛出非法参数异常。

FOCUS_BEFORE_DESCENDANTS

该参数表明 ViewGroup 自身先处理焦点,如果没有处理则分发给子View进行处理。

FOCUS_AFTER_DESCENDANTS

该参数表明子View优先处理焦点,如果所有的子View都没有处理,则 ViewGroup 自身再处理。

FOCUS_BLOCK_DESCENDANTS

该参数表明 ViewGroup 自身处理焦点,不会分发给子View处理。
而这三种参数实际上是在 requestFocus(int direction, Rect previouslyFocusedRect) 方法中起作用的,如下源码所示。

    /**
     * {@inheritDoc}
     *
     * Looks for a view to give focus to respecting the setting specified by
     * {@link #getDescendantFocusability()}.
     *
     * Uses {@link #onRequestFocusInDescendants(int, android.graphics.Rect)} to
     * find focus within the children of this group when appropriate.
     *
     * @see #FOCUS_BEFORE_DESCENDANTS
     * @see #FOCUS_AFTER_DESCENDANTS
     * @see #FOCUS_BLOCK_DESCENDANTS
     * @see #onRequestFocusInDescendants(int, android.graphics.Rect) 
     */
    @Override
    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        if (DBG) {
            System.out.println(this + " ViewGroup.requestFocus direction="
                    + direction);
        }
        int descendantFocusability = getDescendantFocusability();

        switch (descendantFocusability) {
            case FOCUS_BLOCK_DESCENDANTS:
                return super.requestFocus(direction, previouslyFocusedRect);
            case FOCUS_BEFORE_DESCENDANTS: {
                final boolean took = super.requestFocus(direction, previouslyFocusedRect);
                return took ? took : onRequestFocusInDescendants(direction, previouslyFocusedRect);
            }
            case FOCUS_AFTER_DESCENDANTS: {
                final boolean took = onRequestFocusInDescendants(direction, previouslyFocusedRect);
                return took ? took : super.requestFocus(direction, previouslyFocusedRect);
            }
            default:
                throw new IllegalStateException("descendant focusability must be "
                        + "one of FOCUS_BEFORE_DESCENDANTS, FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS "
                        + "but is " + descendantFocusability);
        }
    }

如果想让 RecyclerView 的子View优先获取焦点的话,就可以在布局中添加下面这一行代码。

android:descendantFocusability="afterDescendants"

或者在Java代码中添加下面这一行代码。

mRecyclerView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
上一篇下一篇

猜你喜欢

热点阅读