美文网首页
Android 小知识

Android 小知识

作者: 唐洪峰 | 来源:发表于2018-01-08 10:51 被阅读0次
    Activity启动方式singleTop

    task栈场景:
    Activity B
    Acitivty A (singleTop)
    此时在Activity B中如果需要finish B并启动A,一定要先finish B再启动A,否则依然会有两个A存在。

    1. B启动A情况一
    startActivity(intent);
    finish();
    

    结果:
    Acitivty A
    Acitivty A

    1. B启动A情况二
    finish();
    startActivity(intent);
    

    结果:
    Acitivty A

    资源文件限定符
    1. 限定符(mdpi,tvdpi,hdpi,xhdpi ……)可以适配屏幕像素密度
    2. 限定符(land,port)可以适配屏幕横竖屏状态
    3. 限定符(1024x600 ……)可以适配计算虚拟键或者不计算虚拟键的屏幕
    4. 限定符(ldrtl)可以适配从右往左的布局习惯
    5. 限定符(zh,th ……)可以适配语言
    6. 限定符(rCN, rPT ……)可以适配ISO 3166-1
      layout: 常规布局
      layout-ldrtl: 从右往左(书写习惯)的国家的布局
      values-th: 语言(泰语)的values
      values-land: 横屏布局
      drawable-ldrtl-mdpi:从右往左(书写习惯)的国家的mdpi屏幕像素密度的图片资源
    ViewAdapter的预加载失效,造成滑动时fragment黑屏

    this.getView().setVisibility(menuVisible ? View.VISIBLE : View.GONE)在setMenuVisibility中会导致ViewAdapter的预加载失效,造成滑动时fragment黑屏。

    @Override
    public void setMenuVisibility(boolean menuVisible) {
      super.setMenuVisibility(menuVisible);
      if (mMenuVisible != menuVisible) {
        mMenuVisible = menuVisible;
        if (!menuVisible) {
          updateOnExit();
        } else if (isResumed()) {
          refreshData();
        }
      }
    
      /** add by thf for Dialer UI begin */
      if (com.huaqin.common.featureoption.FeatureOption.HQ_DIALER_UI_LENOVO 
          && this.getView() != null){
        //会造成ViewAdapter的预加载失效    
        this.getView().setVisibility(menuVisible ? View.VISIBLE : View.GONE); 
      }
      /** add by thf for Dialer UI end */
    }
    
    setEnabled将控件设置为不可点击的同时,字体置灰的原因

    通过setEnabled可以将控件设置为不可点击,且置灰。置灰的实现方式是系统会根据系统默认的文字首选颜色来设置文字的颜色,系统默认的文字颜色是个颜色选择器(设置文字state_enabled="false"和state_enabled="true"时的颜色来实现置灰的切换)。如果我们在Activity的主题中重新设置了系统的android:textColorPrimary和android:textColorSecondary后,如果使用的字体颜色没有做enabled状态的区分(比如简单的设置某个颜色,而不是颜色选择器),则会造成在setEnabled(false)的时候,文字并不会被置灰。如要实现置灰,此时需要定义自己的文字颜色选择器,比如:

    <item name="android:textColorPrimary">@color/primary_text_color</item>
    

    primary_text_color.xml:

    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_enabled="false" android:color="#aaaaaa" /> <!-- disabled-->
        <item android:color="#FFFFFF" /> <!-- default -->
    </selector>
    
    moveTaskToback将activity退后台

    方法:public boolean moveTaskToBack(boolean nonRoot)
    activity里有这个方法,参数说明如下:
    nonRoot=false→ 仅当activity为task根(即首个activity例如启动activity之类的)时才生效
    nonRoot=true→ 忽略上面的限制
    这个方法不会改变task中的activity中的顺序,效果基本等同于home键

    应用场景:比如有些activity诸如引导图之类的,用户在按返回键的时候你并不希望退出(默认就finish了),而是只希望置后台,就可以调这个方法。

    此方法可以使得应用在第一次启动之后的再启动过程得到明显的加快。

    @Override
    public void onBackPressed() {
      if(isTaskRoot()) {
        moveTaskToBack(false);
        /// @}
      } else {
        super.onBackPressed();
      }
    }
    
    Theme
    1. <item name="android:windowActionBarOverlay">true</item> 表示actionbar是否悬浮
    2. <item name="android:elevation">@dimen/hq_action_bar_elevation</item> 阴影高度(控制阴影显示)
    3. <itemname="android:actionDropDownStyle">@style/HQDropDownNav</item> android:actionDropDownStyle控制actiongbar上的下拉导航外部按钮的样式
    4. <itemname="android:dropDownListViewStyle">@style/MyDropDownListView</item> android:dropDownListViewStyle控制actiongbar上的下拉导航内部按钮的样式
    nine-patch图片:

    nine-patch图片针对android程序有效,用于控制图片作为背景在拉伸时的行为。四个边框上的黑线代表的意思分表为:上边黑线代表图片左右拉伸时的拉伸区域,左边黑线代表图片上下拉伸时的拉伸区域,下边黑线和右边黑线交叉区域代表填充区域(文字的所在区域)。

    EditText字数限制问题:

    方法一:
    在xml布局文件中设置文本编辑框属性作为字符数限制
    如:android:maxLength="10"即限制最大输入字符个数为10
    方法二:
    在代码中使用android.text.InputFilter进行过滤
    editText.setFilter(new InputFilter[]{new InputFilter.LengthFilter(20)});即限定最大输入字符数为20
    方法三:
    利用TextWatcher进行监听

    /*
     * 监听输入内容是否超出最大长度,并设置光标位置
     * */  
    public class MaxLengthWatcher implements TextWatcher {  
      private int maxLen = 0;  
      private EditText editText = null;  
      public MaxLengthWatcher(int maxLen, EditText editText) {  
        this.maxLen = maxLen;  
        this.editText = editText;  
      }  
    
      public void afterTextChanged(Editable arg0) {  
        // TODO Auto-generated method stub  
      }  
    
      public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,  
               int arg3) {  
        // TODO Auto-generated method stub  
      }  
    
      public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {  
        // TODO Auto-generated method stub  
        Editable editable = editText.getText();  
        int len = editable.length();  
        if(len > maxLen)  {  
          int selEndIndex = Selection.getSelectionEnd(editable);  
          String str = editable.toString();  
          //截取新字符串  
          String newStr = str.substring(0,maxLen);  
          editText.setText(newStr);  
          editable = editText.getText();  
          //新字符串的长度  
          int newLen = editable.length();  
          //旧光标位置超过字符串长度  
          if(selEndIndex > newLen)  {
            selEndIndex = editable.length();  
          }  
          //设置新光标所在的位置  
          Selection.setSelection(editable, selEndIndex);  
        }  
      }  
    }  
    
    import android.app.Activity;  
    import android.os.Bundle;  
    import android.text.InputFilter;  
    import android.widget.EditText;  
    
    public class TextEditActivity extends Activity {  
      /** Called when the activity is first created. */  
      @Override  
      public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        EditText editText = (EditText) findViewById(R.id.entry);  
        editText.addTextChangedListener(new MaxLengthWatcher(10, editText));  
      }  
    }  
    
    EditText输入键盘设置和输入字符限制方式:

    方法一:

    android:digits="0123456789xyzXYZ"
    android:inputType="number"
    

    方法二:

    edittext.setKeyListener(new NumberKeyListener(){
      protected char[] getAcceptedChars(){
          char[] numberChars = {'1','2','3','4','5','6','7','8','9','0'};  //限制输入字符
          return numberChars;
      }
    
      public int getInputType(){
          return android.text.InputType.TYPE_CLASS_NUMBER;  //键盘类型
      }
    });
    

    具体键盘类型可以在android.text.InputType中查找。

    PopupMenu显示位置的问题:

    关于PopupMenu的显示位置,默认情况下的显示是以关联控件(弹出PopupMenu控件的控件)的左下角为PopupMenu的起始位置(右上角),即显示在关联控件的下面。在主题样式中可以通过设置:

    <item name="android:overlapAnchor">true</item>
    

    来改变PopupMenu的显示方式:true表示关联控件的起始位置即是PopupMenu起始位置,false表示关联控件的左下角为PopupMenu的起始位置(默认情况)。
    TextView使用setMaxLines(n)不起作用问题:
    由于在通用控件中可能设置了singleLine = true,所以直接使用setMaxLines(n)是不起作用的。
    可以如下方式设置:

    TextView tv = (TextView) parent.findViewById(R.id.title);
    tv.setSingleLine(false);
    tv.setMaxLines(n);
    tv.setEllipsize(TextUtils.TruncateAt.valueOf("END"));
    
    Android xml资源文件中 @, @android:type, @*, ?, @+ 含义和区别:
    1. @代表引用资源
      a) 引用非系统资源。格式:@[package]type/name
      android:text="@string/hello"
      b) 引用系统资源。格式:@android:type/name
      android:textColor="@android:color/opaque_red"
      注意:其实@android:type/name@[package]type/name的一个子类
    2. @*代表引用系统的非public资源。格式:@*android:type/name
      系统资源定义分public和非public。public的声明在:
      frameworks\base\core\res\res\values\public.xml
      @*android:type/name:可以调用系统定义的所有资源
      @android:type/name:只能调用public属性的资源
      注意:没有在public.xml中声明的资源是google不推荐使用的。
    3. ?代表引用主题属性
      另外一种资源允许你引用当前主题中的属性的值。这个属性值只能在style资源和XML属性中使用;它允许你通过将他们改变为当前主题提供的标准变化来改变UI元素的外观,而不是提供具体的值。例如:
      android:textColor="?android:textDisabledColor"
      注意,这和资源引用非常类似,除了我们使用一个”?“前缀代替了”@“。当你使用这个标记时,你就提供了属性资源的名称,它将在主题中被查找,所以你不需要显示声明这个类型(如果声明,其形式就是?android:attr/android:textDisabledColor)。除了使用这个资源的标识符来查询主题中的值替代原始的资源,其命名语法和”@“形式一致:
      ?[namespace:]type/name,这里类型是可选。
    4. @+代表在创建或引用资源。格式:@+type/name
      含义:”+“表示在R.java中名为type的内部类中添加一条记录。如:@+id/button的含义是在R.java文件中的id这个静态内部类添加一条常量名button。该常量就是该资源的标识符。如果标识符(包括系统资源)已经存在则表示引用该标识符。最常用的就是在定义资源ID中,例如:
      @+id/资源ID名 新建一个资源ID
      @id/资源ID名 引用现有已定义的资源ID,包括系统资源ID
      @android:id/资源ID名 引用系统资源ID,其等效于@id/资源ID名
    动态创建EditView等控件注意事项
    1. setSelection方法必须在setInputType方法之后,否则不会生效。
    2. new出来的视图控件setLayoutParams如果不生效,需要将该控件加入到父视图中以后再setLayoutParams。
    3. setEnabled有如下行为:
      a) android中禁用/允许(setEnabled(false)/setEnabled(true))父视图并不会禁用/允许子视图,也就是说当你使用的View是ViewGroup的时候,子视图是不会被同时被setEnabled的。
    private void setEnabledAll(View v, boolean enabled) {
        v.setEnabled(enabled);
        v.setFocusable(enabled);
        if(v instanceof ViewGroup) {
            ViewGroup vg = (ViewGroup) v;
            for (int i = 0; i < vg.getChildCount(); i++)
                setEnabledAll(vg.getChildAt(i), enabled);
        }
    }
    

    b) android中禁用/允许(setEnabled(false)/setEnabled(true))视图,该视图仍然是可以获取焦点和获得键盘输入的。
    c) android中禁用视图置灰显文字,而不会灰显图标。这是因为系统中默认的文字颜色@color/primary_text_color实际上是一个文字选择器,该选择器设置了state_enabled="false"时文字的颜色。

    关于Preference的onCreateView和onBindView

    这两个方法在Preference初始化的时候调用顺序是先onCreateView再onBindView。且在onBindView中会根据Preference的初始综合状态重新设置其及子preference的enabled状态。所以通常我们自定义Preference的时候,xml布局的inflate应该放在onCreateView中,而控件的具体业务操作则应该放在onBindView中,以防止被onBindView默认的操作行为覆盖。比如我们如果在onCreateView中对子控件进行setEnabled操作会是无效的,因为onBindView会重新设置控件的Enabled状态(只与初始化状态有关,与业务无关)。

    Android中的静态资源引用

    在android中对资源引用一般使用getResource().getString(R.string.xxx);这个属于静态资源引用,其引用的是编译本APK时由aapt生成的R.java中的Id。一般情况下,引用本apk的资源是不会有问题的(因为这个R.java就是本APK的资源Id对应关系)。但如果引用系统资源,依然使用这种方式:getResource().getString(android.xxx.R.string.xxx);则有可能会发生不可预料的问题。因为系统的android.xxx.R.java文件是在对应平台编译的时候由aapt生成的。而自己的APK在编译的时候是引用的当前环境的系统资源。如果把这个APK放在编译时的系统环境中运行是不会有问题的,但如果放到其他的android平台中,则有可能会发生不可预料的问题,因为其他平台的系统资源不一定是一致的,因此它的R.java的资源对应关系也不一定与原平台是一致的。而我们的APK保存的系统资源ID的索引的是原平台系统的,这就会造成Id对应混乱,而产生不可预料的问题。

    杂项
    1. 修改manifest文件可能需要重启机器才能生效。 在没有修改模块代码的情况下,修改宏,当在Android.mk文件中使用该宏对AndroidManifest.xml的编译进行控制的时候,如果开机做了某些优化,push进去的模块代码的AndroidManifest.xml在重启后并不会生效,而会使用旧的AndroidManifest.xml。也就是说开机时,当某些开机优化程序发现模块代码没有变动的时候,不会去加载改变了的AndroidManifest.xml。
    2. SystemProperties的值在手机system/build.prop中。由源码中的system.prop文件和.mk文件中的PRODUCT_PROPERTY_OVERRIDES属性(添加方式,如:PRODUCT_PROPERTY_OVERRIDES += ro.com.android.mobiledata=false)通过编译生成。
    3. bindService的时候,如果在onbind方法中返回的是一个空对象,就不调用ServiceConnection的onServiceConnected方法。

    相关文章

      网友评论

          本文标题:Android 小知识

          本文链接:https://www.haomeiwen.com/subject/cawvnxtx.html