最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android輸入法彈出時覆蓋輸入框問題的解決方法

 更新時間:2016年04月19日 14:07:27   作者:xueshanhaizi  
這篇文章主要介紹了Android輸入法彈出時覆蓋輸入框問題的解決方法的相關(guān)資料,需要的朋友可以參考下

 當(dāng)一個activity中含有輸入框時,我們點擊輸入框,會彈出輸入法界面,整個界面的變化效果與manifest中對應(yīng)設(shè)置的android:windowSoftInputMode屬性有關(guān),一般可以設(shè)置的值如下,

<activity android:windowSoftInputMode=[
"stateUnspecified",
"stateUnchanged”, 
"stateHidden",
"stateAlwaysHidden”, 
"stateVisible",
"stateAlwaysVisible”, 
"adjustUnspecified",
"adjustResize”, 
"adjustPan"] …… >

       具體怎么設(shè)置可以查看官方文檔。今天主要解決當(dāng)輸入法彈出時會覆蓋輸入框的問題。

什么情況會覆蓋?

       當(dāng)android的應(yīng)用中如果一個activity設(shè)置了全屏屬性Theme.Light.NotittleBar.Fullscreen或者設(shè)置了activity對應(yīng)的主題中android:windowTranslucentStatus屬性,設(shè)置方式為:<item name="android:windowTranslucentStatus">true</item>,這是如果對應(yīng)的頁面上含有輸入框,將會導(dǎo)致點擊輸入框時軟鍵盤彈出后鍵盤覆蓋輸入框,導(dǎo)致輸入框看不見。

為什么?

       這其實是因為在全屏?xí)r,adjustResize屬性已經(jīng)失效了,該問題是系統(tǒng)的一個bug,參考鏈接。adjustResize不生效,那有沒有其他方法來解決吶? 這時我們可以設(shè)置adjust屬性為adjustPan屬性,該屬性不會失效,但是由于adjustPan會將頁面整體平移,以留出輸入法空間,會有一個抖動的效果,體驗很差,哪有沒有體驗效果更好的方法吶?

解決方案:

       如果跟布局采用FrameLayout,則可以復(fù)寫一個自定義FrameLayout,同時設(shè)置FrameLayout的android:fitsSystemWindows屬性為true。xml設(shè)置如下

<com.sample.ui.widget.InsetFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:fitsSystemWindows="true”>

       我們自定義該FrameLayout為InsetFrameLayout,InsetFrameLayout 代碼如下:

public final class InsetFrameLayout extends FrameLayout {
  private int[] mInsets = new int[4];

  public InsetFrameLayout(Context context) {
    super(context);
  }

  public InsetFrameLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public InsetFrameLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  public final int[] getInsets() {
    return mInsets;
  }

  @Override
  protected final boolean fitSystemWindows(Rect insets) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      // Intentionally do not modify the bottom inset. For some reason,
      // if the bottom inset is modified, window resizing stops working.

      mInsets[0] = insets.left;
      mInsets[1] = insets.top;
      mInsets[2] = insets.right;

      insets.left = 0;
      insets.top = 0;
      insets.right = 0;
    }

    return super.fitSystemWindows(insets);
  }
  @Override
  public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
      mInsets[0] = insets.getSystemWindowInsetLeft();
      mInsets[1] = insets.getSystemWindowInsetTop();
      mInsets[2] = insets.getSystemWindowInsetRight();
      return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
          insets.getSystemWindowInsetBottom()));
    } else {
      return insets;
    }
  }

}

官方解決方案:

       官方其實也發(fā)現(xiàn)了問題,因此在android.support.design.internal下也重寫了FrameLayout來解決該問題,但是該類被標(biāo)記了hide。

/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.support.design.internal;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.design.R;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.WindowInsetsCompat;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

/**
 * @hide
 */
public class ScrimInsetsFrameLayout extends FrameLayout {

  private Drawable mInsetForeground;

  private Rect mInsets;

  private Rect mTempRect = new Rect();

  public ScrimInsetsFrameLayout(Context context) {
    this(context, null);
  }

  public ScrimInsetsFrameLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public ScrimInsetsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    final TypedArray a = context.obtainStyledAttributes(attrs,
        R.styleable.ScrimInsetsFrameLayout, defStyleAttr,
        R.style.Widget_Design_ScrimInsetsFrameLayout);
    mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsFrameLayout_insetForeground);
    a.recycle();
    setWillNotDraw(true); // No need to draw until the insets are adjusted

    ViewCompat.setOnApplyWindowInsetsListener(this,
        new android.support.v4.view.OnApplyWindowInsetsListener() {
          @Override
          public WindowInsetsCompat onApplyWindowInsets(View v,
              WindowInsetsCompat insets) {
            if (null == mInsets) {
              mInsets = new Rect();
            }
            mInsets.set(insets.getSystemWindowInsetLeft(),
                insets.getSystemWindowInsetTop(),
                insets.getSystemWindowInsetRight(),
                insets.getSystemWindowInsetBottom());
            setWillNotDraw(mInsets.isEmpty() || mInsetForeground == null);
            ViewCompat.postInvalidateOnAnimation(ScrimInsetsFrameLayout.this);
            return insets.consumeSystemWindowInsets();
          }
        });
  }

  @Override
  public void draw(@NonNull Canvas canvas) {
    super.draw(canvas);

    int width = getWidth();
    int height = getHeight();
    if (mInsets != null && mInsetForeground != null) {
      int sc = canvas.save();
      canvas.translate(getScrollX(), getScrollY());

      // Top
      mTempRect.set(0, 0, width, mInsets.top);
      mInsetForeground.setBounds(mTempRect);
      mInsetForeground.draw(canvas);

      // Bottom
      mTempRect.set(0, height - mInsets.bottom, width, height);
      mInsetForeground.setBounds(mTempRect);
      mInsetForeground.draw(canvas);

      // Left
      mTempRect.set(0, mInsets.top, mInsets.left, height - mInsets.bottom);
      mInsetForeground.setBounds(mTempRect);
      mInsetForeground.draw(canvas);

      // Right
      mTempRect.set(width - mInsets.right, mInsets.top, width, height - mInsets.bottom);
      mInsetForeground.setBounds(mTempRect);
      mInsetForeground.draw(canvas);

      canvas.restoreToCount(sc);
    }
  }

  @Override
  protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (mInsetForeground != null) {
      mInsetForeground.setCallback(this);
    }
  }

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    if (mInsetForeground != null) {
      mInsetForeground.setCallback(null);
    }
  }

}

       采用如上其中的任何一種方法就可以解決輸入法彈出后覆蓋輸入框問題。

其他問題?

       在我們使用的過程中發(fā)現(xiàn)有用戶反饋,說只要進入我們采用該布局的頁面就會崩潰,我們查看了崩潰日志,發(fā)現(xiàn)有部分手機都使用了相同的一個安卓系統(tǒng),并且版本都是19,android4.4.x,一個被重寫過的系統(tǒng),該系統(tǒng)的代碼加載方式被重寫了。

為什么會崩潰?

       我們代碼使用到了WindowInsets,該類是api 20才提供的,因此19的系統(tǒng)中其實是沒有該代碼的,但是該系統(tǒng)在xml的inflate的時候就解析了該類,導(dǎo)致classNotFound。

新的解決方案!

       新的解決方案還是采用了上述的方式,不過會針對不同的版本寫不一樣的布局,分別為api 20以上與20以下提供不同的布局,這是采用系統(tǒng)的限定符實現(xiàn)的,之后20以上的原樣采用上述的方式,20以下去掉onApplyWindowInsets復(fù)寫,這樣不同的版本加載不同的代碼就OK了。

 @Override
  public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
      mInsets[0] = insets.getSystemWindowInsetLeft();
      mInsets[1] = insets.getSystemWindowInsetTop();
      mInsets[2] = insets.getSystemWindowInsetRight();
      return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
          insets.getSystemWindowInsetBottom()));
    } else {
      return insets;
    }
  }

總結(jié)到此整個解決方案已經(jīng)完成了,如過有更新的解決方案望大家分享。

相關(guān)文章

  • 手把手教你用ViewPager自定義實現(xiàn)Banner輪播

    手把手教你用ViewPager自定義實現(xiàn)Banner輪播

    這篇文章主要手把手教你用ViewPager自定義實現(xiàn)Banner輪播,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android編程實現(xiàn)Dialog窗體監(jiān)聽的方法

    Android編程實現(xiàn)Dialog窗體監(jiān)聽的方法

    這篇文章主要介紹了Android編程實現(xiàn)Dialog窗體監(jiān)聽的方法,結(jié)合實例形式分析了Android針對Dialog對話框窗體事件監(jiān)聽與響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • Android結(jié)束進程的方法詳解

    Android結(jié)束進程的方法詳解

    這篇文章主要介紹了Android結(jié)束進程的方法,結(jié)合實例形式分析了Android結(jié)束進程的具體步驟,實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下
    2016-03-03
  • Android中利用NetworkInfo判斷網(wǎng)絡(luò)狀態(tài)時出現(xiàn)空指針(NullPointerException)問題的解決方法

    Android中利用NetworkInfo判斷網(wǎng)絡(luò)狀態(tài)時出現(xiàn)空指針(NullPointerException)問題的解決

    這篇文章主要介紹了Android中利用NetworkInfo判斷網(wǎng)絡(luò)狀態(tài)時出現(xiàn)空指針(NullPointerException)問題的解決方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-11-11
  • Android編程實現(xiàn)一鍵鎖屏的方法

    Android編程實現(xiàn)一鍵鎖屏的方法

    這篇文章主要介紹了Android編程實現(xiàn)一鍵鎖屏的方法,結(jié)合實例詳細(xì)分析了鎖屏功能所涉及的類與具體功能實現(xiàn)技巧,需要的朋友可以參考下
    2015-11-11
  • Android內(nèi)存優(yōu)化雜談

    Android內(nèi)存優(yōu)化雜談

    這篇文章主要介紹了Android內(nèi)存優(yōu)化的方法,重點介紹優(yōu)化RAM,即降低運行時內(nèi)存,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-12-12
  • 擁抱kotlin之如何習(xí)慣使用kotlin高階函數(shù)

    擁抱kotlin之如何習(xí)慣使用kotlin高階函數(shù)

    這篇文章主要給大家介紹了關(guān)于擁抱kotlin之如何習(xí)慣使用kotlin高階函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用kotlin具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Android一行代碼實現(xiàn)圓形頭像

    Android一行代碼實現(xiàn)圓形頭像

    本篇文章主要介紹了Android一行代碼實現(xiàn)圓形頭像的相關(guān)知識,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-05-05
  • 如何在android中制作一個方向輪盤詳解

    如何在android中制作一個方向輪盤詳解

    這篇文章主要給大家介紹了關(guān)于如何在android中制作一個方向輪盤的相關(guān)資料,這個是在手游領(lǐng)域中很常見的用于控制方向的輪盤,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • Android實現(xiàn)隨手指移動小球

    Android實現(xiàn)隨手指移動小球

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)隨手指移動小球,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08

最新評論

健康| 武清区| 耒阳市| 禄劝| 茶陵县| 台前县| 蕲春县| 蓬溪县| 嘉峪关市| 台北县| 平乐县| 冷水江市| 民丰县| 阿拉善左旗| 南投县| 大同市| 鸡东县| 宿松县| 新丰县| 华蓥市| 台中县| 太谷县| 涞源县| 巴彦县| 连江县| 宝山区| 武清区| 修文县| 南平市| SHOW| 宾阳县| 双牌县| 望奎县| 嵩明县| 冀州市| 南雄市| 延长县| 嵊泗县| 枝江市| 长宁区| 广东省|