码迷,mamicode.com
首页 > 其他好文 > 详细

TextView在xml文件中加入onClick属性后,clickable值依旧是false的原因。

时间:2015-09-27 20:04:26      阅读:416      评论:0      收藏:0      [点我收藏+]

标签:

先看View中是如何定义clickable和onClick的:

                case com.android.internal.R.styleable.View_clickable:
                    if (a.getBoolean(attr, false)) {
                        viewFlagValues |= CLICKABLE;
                        viewFlagMasks |= CLICKABLE;
                    }
                    break;

上面这段代码是View源码中对clickable属性的定义,缺省值为false。

                case R.styleable.View_onClick:
                    if (context.isRestricted()) {
                        throw new IllegalStateException("The android:onClick attribute cannot "
                                + "be used within a restricted context");
                    }

                    final String handlerName = a.getString(attr);
                    if (handlerName != null) {
                        setOnClickListener(new OnClickListener() {
                            private Method mHandler;

                            public void onClick(View v) {
                                if (mHandler == null) {
                                    try {
                                        mHandler = getContext().getClass().getMethod(handlerName,
                                                View.class);
                                    } catch (NoSuchMethodException e) {
                                        int id = getId();
                                        String idText = id == NO_ID ? "" : " with id ‘"
                                                + getContext().getResources().getResourceEntryName(
                                                    id) + "‘";
                                        throw new IllegalStateException("Could not find a method " +
                                                handlerName + "(View) in the activity "
                                                + getContext().getClass() + " for onClick handler"
                                                + " on view " + View.this.getClass() + idText, e);
                                    }
                                }

                                try {
                                    mHandler.invoke(getContext(), View.this);
                                } catch (IllegalAccessException e) {
                                    throw new IllegalStateException("Could not execute non "
                                            + "public method of the activity", e);
                                } catch (InvocationTargetException e) {
                                    throw new IllegalStateException("Could not execute "
                                            + "method of the activity", e);
                                }
                            }
                        });
                    }
                    break;

上面是onClick属性在View源码中的定义。可以看到它调用了setOnClickListener()方法对点击事件进行注册,下面看下setOnClickListener()方法的源码:

    /**
     * Register a callback to be invoked when this view is clicked. If this view is not
     * clickable, it becomes clickable.
     *
     * @param l The callback that will run
     *
     * @see #setClickable(boolean)
     */
    public void setOnClickListener(OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }

如果clickable属性是false那么在调用此方法后就会变为true。

继承自View的Button、ImageView控件在xml里使用onClick属性时,通过打印日志可以看到clickable由默认的false变为了true,可是同样继承自View的TextView依旧是false。为什么会出现这种情况呢?

那就要了解Android加载xml文件的过程。

以View为例进行说明。我们使用setOnContentView()方法加载布局文件时。布局文件中的View元素会调用下面的这个构造器来新建一个View对象

技术分享
    /**
     * Constructor that is called when inflating a view from XML. This is called
     * when a view is being constructed from an XML file, supplying attributes
     * that were specified in the XML file. This version uses a default style of
     * 0, so the only attribute values applied are those in the Context‘s Theme
     * and the given AttributeSet.
     *
     * <p>
     * The method onFinishInflate() will be called after all children have been
     * added.
     *
     * @param context The Context the view is running in, through which it can
     *        access the current theme, resources, etc.
     * @param attrs The attributes of the XML tag that is inflating the view.
     * @see #View(Context, AttributeSet, int)
     */
    public View(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
View Code

this(context, attrs, 0);又会调用 public View(Context context, AttributeSet attrs, int defStyleAttr){}构造器。可以看到onClick属性在定义时调用的setOnClickListener()方法是在对象被创建时调用的

下面再来看TextView控件,他在构造器中对clickable又进行了一些处理

        boolean focusable = mMovement != null || getKeyListener() != null;
        boolean clickable = focusable;
        boolean longClickable = focusable;

        n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr = a.getIndex(i);

            switch (attr) {
            case com.android.internal.R.styleable.View_focusable:
                focusable = a.getBoolean(attr, focusable);
                break;

            case com.android.internal.R.styleable.View_clickable:
                clickable = a.getBoolean(attr, clickable);
                break;

            case com.android.internal.R.styleable.View_longClickable:
                longClickable = a.getBoolean(attr, longClickable);
                break;
            }
        }

从代码中可以看到clickable的缺省值变成了focuseable的值,TextView在调用构造器创造新的对象的时候会默认调用父类的构造器,也就是说经过setOnClickListener()处理过的clickable值是变成了true,可是在TextView的构造器中又被赋予了新的值。这也可以解释说为什么TextView控件在xml文件中用了onClick属性后clickable的值依旧是false,而在代码中调用setOnClickListener()方法后,clickable值就变成了true,那是因为在代码中调用的setOnClickListener()方法是在TextView对象被建立之后。

TextView在xml文件中加入onClick属性后,clickable值依旧是false的原因。

标签:

原文地址:http://www.cnblogs.com/-syi/p/4842617.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!