• EditText: android:focusable和android:focusableInTouchMode的区别


    android:focusable
    之所以有这个属性主要是因为Android系统不仅仅是针对手机的,有可能在电视、手表等等的非触摸输入设备上(如Android TV),这些设备只有物理上下键不具备触摸功能,
    那么当把这个属性值设置为true的时候,比方说你按了一下向下键,屏幕上的内容就会对应选中一个向下的控件(如果这个控件设置android:focusable = true的话),否则
    就会选中下一个具备focusable能力的控件。


    android:focusableInTouchMode
    与上面那种情况相反,如果是针对手机开发的话,那么大部分手机都具备触摸功能,那么这个属性有什么作用呢?
    从交互的角度上讲,焦点的作用其实就是为了提示用户当前控件已被选中了,可以进行下一步的操作。比如在Android 5.0上新推出的Material Design效果上面,如果一个EditText被选中了,那么它的
    输入框就会更换颜色以示区别。但是在手机开发中并不是所有的控件都需要有选中这种状态,通常在点击后可能只想达到某种效果(如点击按钮就是想触发点击事件,不需要有选中效果),那么这个时候
    如果把focusableInTouchMode设置为true,此时执行的就是更换焦点操作,相应的事件就无法及时得到响应,这样的体验就很不好。
    例:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ddffff"
        android:gravity="center"
        android:orientation="vertical"
        android:focusableInTouchMode="true"
        >
    
        <View
            android:id="@+id/view_test"
            android:layout_width="100dip"
            android:layout_height="100dip"
            android:focusableInTouchMode="true"
            android:background="#ff0000"
            />
    
    
        <Button
            android:id="@+id/bt_test"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:text="click me"
            android:focusableInTouchMode="true"
            />
    
    </LinearLayout>

     我们分别为 LinearLayout , View , Button 都增加一个触摸时能够获取到焦点的属性。

    package com.yuneec.testdemo;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity {
    
    
    
        private View view_test;
        private Button bt_test;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            view_test = findViewById(R.id.view_test);
            bt_test = (Button) findViewById(R.id.bt_test);
    
            view_test.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.i("xp.chen", "I am view, click................");
                }
            });
    
            view_test.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    Log.i("xp.chen", "==========================================");
                    Log.i("xp.chen", "I am view, focus: "+view_test.isFocused());
                    Log.i("xp.chen", "I am button, focus: "+bt_test.isFocused());
                }
            });
    
            bt_test.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.i("xp.chen", "I am button, click................");
                }
            });
    
            bt_test.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    Log.i("xp.chen", "==========================================");
                    Log.i("xp.chen", "I am button, focus: "+bt_test.isFocused());
                    Log.i("xp.chen", "I am view, focus: "+view_test.isFocused());
                }
            });
        }
    
    }

    我们先点击View, 发现View的onClick事件并未打印,再点击View,发现View的OnClick事件可以正常打印了;

    然后再点击Button,发现Button的OnClick事件也未打印,再点击一次Button,发现Button的onClick事件可以正常打印了。

    这说明第一次点击View或者Button,只是单纯的将焦点转换到了View或者Button上,此时会调用 OnFocusChangeListener 方法,只有当再次点击的时候才会调用onClick方法。

    因此,这种操作对Button来说是多余的(我点击哪个Button,就意味着我想触发哪个Button的onClick事件, 不是说点击哪个Button,先去让这个Button获得焦点),而Button的 android:focusableInTouchMode 属性默认也就是false。

    但对  EditText 这种控件来说就不一样了,比方说一个界面上有很多 EditText ,在用户点击了其中一个的时候,就代表用户想要在这个EditText里进行输入,那么这个EditText就必须立即获得焦点,弹出软键盘等待用户输入。事实上在Android源代码里面,EditText的 android:focusableInTouchMode  属性默认也就是 true 。参见AOSP中对EditText的属性定义:

    <style name="Widget.EditText">
            <item name="android:focusable">true</item>
            <item name="android:focusableInTouchMode">true</item>
            <item name="android:clickable">true</item>
            <item name="android:background">?android:attr/editTextBackground</item>
            <item name="android:textAppearance">?android:attr/textAppearanceMediumInverse</item>
            <item name="android:textColor">?android:attr/editTextColor</item>
            <item name="android:gravity">center_vertical</item>
        </style>

    可以尝试下将EditText的 android:focusableInTouchMode 属性设置为false,这样在手机上点击EditText,由于获取不到焦点,软键盘无法弹出。

    参考链接:

    Android中最详细的焦点问题,从概念出发带你一点点分享(1)

  • 相关阅读:
    Codeforces 994B. Knights of a Polygonal Table
    Codeforces 994A. Fingerprints
    Codeforces 988F. Rain and Umbrellas
    51nod 1158 全是1的最大子矩阵(单调栈 ,o(n*m))
    51nod 1102 面积最大的矩形 && 新疆大学OJ 1387: B.HUAWEI's billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))
    Codeforces 988E. Divisibility by 25
    【复习资料】单片机与嵌入式系统原理及应用
    Codeforces 723D. Lakes in Berland
    Codeforces 986A. Fair(对物品bfs暴力求解)
    Codeforces 986B. Petr and Permutations(没想到这道2250分的题这么简单,早知道就先做了)
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/10607997.html
Copyright © 2020-2023  润新知