简体   繁体   English

如何在android中创建键盘键等按钮?

[英]How to create buttons like keyboard keys in android?

This question seems trivial. 这个问题似乎微不足道。 I want to create a button like keyboard keys for my app. 我想为我的应用创建一个像键盘键的按钮。 When I click on it, a popup window appears above that button showing the letter pressed. 当我点击它时,一个弹出窗口出现在该按钮上方,显示按下的字母。 Everything works great till now except one thing. 除了一件事以外,一切都很好。 When I add onFocusChangedListener to the button, nothing happens. 当我将onFocusChangedListener添加到按钮时,没有任何反应。 I need to let my button act as a keyboard key, but I don't know how. 我需要让我的按钮充当键盘键,但我不知道如何。

键盘按钮示例

As you can see here, when a button is focused, a popup window appears. 正如您在此处所看到的,当按钮聚焦时,会出现一个弹出窗口。 I want to do that, but onFocusChangeListener doesn't work. 我想这样做,但onFocusChangeListener不起作用。 I know I can use a KeyboardView to achieve that, but I don't want to use that due to some other issues like centering buttons and setting keys' height with layout_weight. 我知道我可以使用KeyboardView来实现这一点,但我不想使用它,因为一些其他问题,如居中按钮和设置键的高度与layout_weight。 So I need to make it with normal buttons. 所以我需要使用普通按钮。

What I tried: 我尝试了什么:

My First Try: 我的第一次尝试:

button.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        if (hasFocus) {
            popupWindow.showAtLocation(keyboardPopup, Gravity.NO_GRAVITY, location.left - 10, location.top - button.getHeight());
        } else {
            popupWindow.dismiss();
        }
    }
});

Result: Nothing happened. 结果:什么都没发生。 The popup window didn't appear at all. 弹出窗口根本没有出现。

Edit: After I have added button.setFocusableInTouchMode(true); 编辑:我添加了button.setFocusableInTouchMode(true); as Ashley suggested, onFocusChanged is now getting called, but it acts so weird. 正如阿什利建议的那样,onFocusChanged现在正在被召唤,但它的行为非常奇怪。 The popup is sometimes shown, but at the same time when it is shown, it never disappears... 弹出窗口有时会显示,但在显示时,它永远不会消失......

My Second Try: 我的第二次尝试:

button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                popupWindow.showAtLocation(keyboardPopup, Gravity.NO_GRAVITY, location.left - 10, location.top - button.getHeight());
                break;
            case MotionEvent.ACTION_UP:
                popupWindow.dismiss();
                break;
        }
        return true;
    }
});

Result: This one acted so weird. 结果:这个行为很奇怪。 Sometimes the popup shows and sometimes not, but when it is shown, the button didn't also change its state. 有时弹出窗口显示,有时不显示,但是当显示时,按钮也不会改变其状态。 It should have been focused, but nothing happened to the button, it acts as if it was in a normal state (Button's background doesn't change with state_focused declared in my drawable xml). 应该已经集中注意力,但按钮没有任何反应,它就像是处于正常状态一样(Button的背景不会随着我的drawable xml中声明的state_focused而改变)。 It seems that onTouchListener overrides the button's functionality. 似乎onTouchListener会覆盖按钮的功能。

Here is a part of my layout: 这是我布局的一部分:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_weight="3">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="Q"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="W"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="E"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="R"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="T"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="Y"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="U"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="I"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="O"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="P"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <View
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="0.5" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="A"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="S"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="D"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="F"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="G"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="H"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="J"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="K"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="L"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <View
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="0.5" />

    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <View
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1.5" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="Z"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="X"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="C"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="V"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="B"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="N"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <Button
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:text="M"
            android:background="@drawable/keyboard_button"
            android:textColor="#FFFFFF"
            android:onClick="onKeyboardClick" />

        <View
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1.5" />

    </LinearLayout>

</LinearLayout>

In code: 在代码中:

public void onKeyboardClick(View view) {
    //The view pressed is a button.
    final Button button = (Button) view;

    //Create a PopupWindow.
    LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
    final View keyboardPopup = inflater.inflate(R.layout.keyboard_popup, null);
    final PopupWindow popupWindow = new PopupWindow(keyboardPopup, view.getWidth() + 20, view.getHeight());
    TextView keyboardKey = (TextView) keyboardPopup.findViewById(R.id.keyboard_key);
    keyboardKey.setText(button.getText().toString());

    //Get button location to show the popup above it.
    int[] keyLocation = new int[2];
    button.getLocationOnScreen(keyLocation);
    final Rect location = new Rect();
    location.left = keyLocation[0];
    location.top = keyLocation[1];
    location.right = location.left + button.getWidth();
    location.bottom = location.top + button.getHeight();

    //This is a temporary solution. I don't want to use that.
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Show popup.
            popupWindow.showAtLocation(keyboardPopup, Gravity.NO_GRAVITY, location.left - 10, location.top - button.getHeight());
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //Dismiss popup.
                    popupWindow.dismiss();
                }
            }, 200);
        }
    });
}

Any help will be greatly appreciated. 任何帮助将不胜感激。 Thanks. 谢谢。

I suggest you use the second try onTouchListener ! 我建议你使用第二次尝试onTouchListener You had 2 issues with that: 你有2个问题:

1. The button does not change state 1.按钮不会改变状态

Indeed, when you override the onTouchListener you must simulate the state yourself. 实际上,当您覆盖onTouchListener您必须自己模拟状态。 Please take a look at this SO thread for how it is done: "Press and hold" button on Android needs to change states (custom XML selector) using onTouchListener 请看看这个SO线程是如何完成的: Android上的“按住”按钮需要使用onTouchListener更改状态(自定义XML选择器)

2. Sometime shows and sometimes not 2.有时显示,有时不显示

This should not happen, especially if you handle all the relevant touch event cases properly. 这不应该发生,特别是如果您正确处理所有相关的触摸事件案例。 You will want to show the pop up when the user touch down on a button and hide that pop up when a user move out of the button (either by swiping out or taking the finger off the screen). 当用户触摸按钮时,您将希望显示弹出窗口,并在用户移出按钮时隐藏弹出窗口(通过向外滑动或将手指从屏幕上移开)。

Please try the following code sample: 请尝试以下代码示例:

button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                v.setPressed(true);
                showPopupWindow(...);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_OUTSIDE:
            case MotionEvent.ACTION_CANCEL:
                v.setPressed(false);
                hidePopupWindow(...);
                break;
        }
        return true;
    }
});
  • Notice the use of getActionMasked instead of getAction to better handle multi touch. 注意使用getActionMasked而不是getAction来更好地处理多点触摸。
  • Notice the v.setPressed(...); 注意v.setPressed(...); - this will update the button state. - 这将更新按钮状态。
  • Notice the different cases of hiding the pop up. 注意隐藏弹出窗口的不同情况。

I didn't notice it in your code but potentially you left out. 我没有在你的代码中注意到它,但可能你遗漏了。

btn.setFocusableInTouchMode(true);
btn.setFocusable(true);

For the on focus change listener. 对于焦点改变监听器。

holder.sAttedenceList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                if (!parent.hasFocus()) {
                    return;
                }

not the full code but this the general structure that worked for me. 不是完整的代码,而是这对我有用的一般结构。

Instead of setting an OnTouchListener , try subclassing Button and overriding onTouchEvent itself: 而不是设置OnTouchListener ,尝试OnTouchListener Button并重写onTouchEvent本身:

public class KeyboardButton extends Button
{
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                popupWindow.showAtLocation(keyboardPopup, Gravity.NO_GRAVITY, location.left - 10, location.top - button.getHeight());
                break;
            case MotionEvent.ACTION_UP:
                popupWindow.dismiss();
                break;
        }
        return super.onTouchEvent(event);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM