Android开发教程之获取系统输入法高度的正确姿势

Android开发教程之获取系统输入法高度的正确姿势

在Android开发中,有时候需要获取系统输入法的高度,以便处理界面上控件的布局。但是由于不同版本的系统输入法可能存在差异,因此需要采用正确的方法获取系统输入法的高度。

使用ViewTreeObserver实时监听输入法高度变化

在Activity的onCreate方法中可以通过ViewTreeObserver来获取输入法高度。首先需要在布局文件中添加一个布局监听器ViewGroup,然后调用ViewGroup的getViewTreeObserver().addOnGlobalLayoutListener()方法,在监听回调中获取输入法高度。

ViewGroup rootView = findViewById(android.R.id.content);
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect r = new Rect();
        rootView.getWindowVisibleDisplayFrame(r);
        int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top);
        Log.i(TAG, "onGlobalLayout: heightDiff=" + heightDiff);
        // do something with heightDiff
    }
});

这段代码中,首先获取了根视图的可见矩形区域,然后计算了输入法高度与根视图高度的差值,即heightDiff。这个值就是输入法的高度,可以在回调中进行相应处理。

使用反射方法获取系统输入法高度

有时候使用ViewTreeObserver监听输入法高度变化可能会有一定的性能问题,此时可以采用反射的方法获取输入法高度。需要使用反射技术来获取全局InputMethodManager对象,然后再通过对象获取当前系统输入法的调用方法,获取输入法高度。

private int getSystemInputMethodHeight(Activity activity) {
    int statusBarHeight = getStatusBarHeight(activity);

    Class<?> clazz;
    Object obj;
    Field field;
    int height = 0;
    try {
        clazz = Class.forName("com.android.internal.R$dimen");
        obj = clazz.newInstance();
        field = clazz.getField("status_bar_height");
        int x = Integer.parseInt(field.get(obj).toString());
        height = activity.getResources().getDimensionPixelSize(x);
    } catch (Exception e) {
        e.printStackTrace();
    }

    int screenHeight = activity.getResources().getDisplayMetrics().heightPixels;

    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
    Method getMethod = null;
    try {
        getMethod = inputMethodManager.getClass().getMethod("getInputMethodWindowVisibleHeight");
        getMethod.setAccessible(true);
        height = screenHeight - (Integer) getMethod.invoke(inputMethodManager) - statusBarHeight - height;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return height;
}

private int getStatusBarHeight(Activity activity) {
    int statusBarHeight = 0;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        //获取状态栏高度的资源ID
        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
        }
    }
    return statusBarHeight;
}

这段代码中需要注意一下两个点:

  • 反射需要获取全局的InputMethodManager对象,因此需要调用Activity的getSystemService(Context.INPUT_METHOD_SERVICE)方法获取。
  • 在获取输入法高度时,需要先获取状态栏高度和输入法的padding值,最后计算差值就是输入法高度。

示例1:应用中的搜索框

通常在应用中,搜索框通常会使用在页面的最顶部。如果没有考虑到输入法高度,可能会对搜索框造成遮挡。因此,需要计算输入法弹出后的高度,以便使输入框获得合适的布局。

public class MyActivity extends Activity {

    private EditText searchBox;
    private View rootView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity_layout);

        searchBox = findViewById(R.id.search_box);
        rootView = findViewById(android.R.id.content);

        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                rootView.getWindowVisibleDisplayFrame(r);
                int heightDiff = rootView.getRootView().getHeight() - (r.bottom - r.top);
                if (heightDiff > 100) {
                    // 说明输入法弹出
                    RelativeLayout.LayoutParams searchLayoutParams = (RelativeLayout.LayoutParams) searchBox.getLayoutParams();
                    searchLayoutParams.topMargin = heightDiff;
                    searchBox.setLayoutParams(searchLayoutParams);
                } else {
                    // 说明输入法隐藏
                    RelativeLayout.LayoutParams searchLayoutParams = (RelativeLayout.LayoutParams) searchBox.getLayoutParams();
                    searchLayoutParams.topMargin = 0;
                    searchBox.setLayoutParams(searchLayoutParams);
                }
            }
        });
    }
}

这段代码中在onCreate方法中为应用中的根视图添加全局布局监听器,根据输入法高度调整了搜索框的布局设置。

示例2:应用中的输入框

在应用中的一些场景中,输入框可能会出现在底部按钮上方,如底部评论输入框等,我们也需要适配输入法的高度。

public class MyActivity extends Activity {

    private EditText editText;
    private View rootView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity_layout);

        editText = findViewById(R.id.edit_text);
        rootView = findViewById(android.R.id.content);

        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                int inputMethodHeight = getSystemInputMethodHeight(MyActivity.this);
                RelativeLayout.LayoutParams editTextLayoutParams = (RelativeLayout.LayoutParams) editText.getLayoutParams();
                editTextLayoutParams.bottomMargin = inputMethodHeight;
                editText.setLayoutParams(editTextLayoutParams);
            }
        });
    }
}

这段代码中同样使用了ViewTreeObserver监听输入法高度的变化,并计算了输入法的高度,然后在回调中更新了输入框的布局设置。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android开发教程之获取系统输入法高度的正确姿势 - Python技术站

(0)
上一篇 2023年5月25日
下一篇 2023年5月25日

相关文章

  • 用PHP实现验证码功能

    下面是用PHP实现验证码功能的完整攻略,包含两条示例说明: 1. 什么是验证码 验证码(CAPTCHA,全称”Completely Automated Public Turing test to tell Computers and Humans Apart”)是一种通过人类轻松识别,但计算机难以识别的图像或文字,用于区分人类和计算机自动化程序的测试。 2.…

    人工智能概论 2023年5月25日
    00
  • IOS 身份证校验详细介绍及示例代码

    IOS身份证校验详细介绍及示例代码 身份证号作为民族国家的一种重要证件,身份证号检验非常重要。本文详细介绍了IOS平台上如何对身份证号进行校验,以及提供了两个示例代码以供参考。 一、身份证号规则 根据我国国家标准GB11643-1999《公民身份号码》规定,身份证号共计18位,其中最后一位是检验位,前17位是表示省市县地区、年月日、顺序号和性别的数字。具体规…

    人工智能概览 2023年5月25日
    00
  • nodejs教程之环境安装及运行

    下面是关于“nodejs教程之环境安装及运行”的完整攻略。 环境安装 下载安装包 首先,在官网(https://nodejs.org/)上下载相应版本的安装包。 Windows系统 下载后,双击安装包进行安装。根据安装程序中的指示,一步步进行安装即可。 Linux系统 对于Linux系统,可以通过包管理器进行安装。 Ubuntu/Debian 对于Ubunt…

    人工智能概论 2023年5月25日
    00
  • Django1.11配合uni-app发起微信支付的实现

    下面我将为您详细讲解“Django 1.11 配合 uni-app 发起微信支付的实现”的完整攻略。 一、前置条件 在微信公众平台中开通微信支付功能,并获得相关的 APP ID、商户号 和 支付密钥; 安装 WxPayAPI,并将 WxPayAPI 放置在项目的根目录下; 在 Django 中安装 django-rest-framework(DRF) 和 d…

    人工智能概览 2023年5月25日
    00
  • 核爆RPG控制台作弊码大全 控制台代码及使用方法

    核爆RPG控制台作弊码大全 核爆RPG控制台作弊码可以让玩家在游戏中快速获取物品、提升角色等级、修改游戏NPC等等。本文将为玩家介绍核爆RPG控制台作弊码的使用方法以及具体的代码实现。 使用控制台 要使用核爆RPG控制台作弊码,玩家需要先开启游戏的控制台。玩家可以在游戏安装目录下寻找“fallout.ini”文件,然后在文件中添加如下语句: [GamePla…

    人工智能概论 2023年5月25日
    00
  • 讯飞智能无线投影仪AP10W值得入手吗?讯飞智能无线投影仪AP10W体验评测

    讯飞智能无线投影仪AP10W值得入手吗? 简介 讯飞智能无线投影仪AP10W是一款集投影、音箱、智能语音助手于一体的智能家居产品。它采用了数字光学投影技术,支持1080P高清输出,可满足家庭和办公的投影需求。此外,该产品还搭载了小讯智能语音助手,因此用户可以通过语音指令控制投影仪,为用户带来了更加智能的用户体验。 评测 外观体验 讯飞智能无线投影仪AP10W…

    人工智能概览 2023年5月25日
    00
  • C#版Tesseract库的使用技巧

    C#版Tesseract库的使用技巧 概述 Tesseract是一个OCR(Optical Character Recognition)引擎,它可以识别图片中的文字,并将其转换为文本。C#版Tesseract库是Tesseract的一个C#封装库,方便了C#开发者在自己的项目中使用OCR技术。本文将介绍如何使用C#版Tesseract库。 安装C#版Tess…

    人工智能概论 2023年5月25日
    00
  • 如何使用bootstrap框架 bootstrap入门必看!

    如何使用 Bootstrap 框架 什么是 Bootstrap? Bootstrap 是一款由 Twitter 公司设计和开发的前端开发框架,它采用了 HTML、CSS、JavaScript 等技术,为开发者提供了大量的、可复用的 UI 组件和样式,使开发工作更加便捷和高效。 如何使用 Bootstrap? 步骤一:下载 Bootstrap 在开始使用 Bo…

    人工智能概览 2023年5月25日
    00
合作推广
合作推广
分享本页
返回顶部