zoukankan      html  css  js  c++  java
  • 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)

  • 相关阅读:
    Head first javascript(七)
    Python Fundamental for Django
    Head first javascript(六)
    Head first javascript(五)
    Head first javascript(四)
    Head first javascript(三)
    Head first javascript(二)
    Head first javascript(一)
    Sicily 1090. Highways 解题报告
    Python GUI programming(tkinter)
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/10607997.html
Copyright © 2011-2022 走看看