1

在我的 Android 应用程序中,我必须使用放置在 EditTexts 旁边的自定义数字键盘来输入数字,所以我需要:

  1. 当用户点击它们时,EditText 应该有焦点,这样当用户点击一个键时我将有光标位置来插入数字。
  2. 编辑文本焦点时不应出现软键盘(但不能通过设置 android:windowSoftInputMode="stateHidden" 完全隐藏键盘,因为屏幕中有一些搜索框仍需要使用软键盘)

我已经搜索并发现了许多关于在显示键盘时以编程方式隐藏键盘的文章,或者将输入类型/可聚焦....设置为不显示键盘....但它们不符合我的需要。

任何人都有这种情况的解决方案,请帮助我。

4

4 回答 4

1

这个我从 CsipSimple 项目中获得灵感并实现了我自己的

这是相同的代码 Create a Custom NumberPad here is mine 拨号盘的布局只是从 1 到 9 的按钮和 * 和 #

package com.xyz.custom;

import java.util.HashMap;
import java.util.Map;

import com.xyz.payphone.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.media.ToneGenerator;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.widget.ImageButton;
import android.widget.TableLayout;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;

public class DialpadNovanet extends TableLayout implements OnClickListener {

    private OnDialKeyListener onDialKeyListener;
    @SuppressLint("UseSparseArrays")
    private static final Map<Integer, int[]> DIGITS_BTNS = new HashMap<Integer, int[]>();
    private static final String tag = "Dialpad";

    static {
        DIGITS_BTNS.put(R.id.button0, new int[] { ToneGenerator.TONE_DTMF_0,
                KeyEvent.KEYCODE_0 });
        DIGITS_BTNS.put(R.id.button1, new int[] { ToneGenerator.TONE_DTMF_1,
                KeyEvent.KEYCODE_1 });
        DIGITS_BTNS.put(R.id.button2, new int[] { ToneGenerator.TONE_DTMF_2,
                KeyEvent.KEYCODE_2 });
        DIGITS_BTNS.put(R.id.button3, new int[] { ToneGenerator.TONE_DTMF_3,
                KeyEvent.KEYCODE_3 });
        DIGITS_BTNS.put(R.id.button4, new int[] { ToneGenerator.TONE_DTMF_4,
                KeyEvent.KEYCODE_4 });
        DIGITS_BTNS.put(R.id.button5, new int[] { ToneGenerator.TONE_DTMF_5,
                KeyEvent.KEYCODE_5 });
        DIGITS_BTNS.put(R.id.button6, new int[] { ToneGenerator.TONE_DTMF_6,
                KeyEvent.KEYCODE_6 });
        DIGITS_BTNS.put(R.id.button7, new int[] { ToneGenerator.TONE_DTMF_7,
                KeyEvent.KEYCODE_7 });
        DIGITS_BTNS.put(R.id.button8, new int[] { ToneGenerator.TONE_DTMF_8,
                KeyEvent.KEYCODE_8 });
        DIGITS_BTNS.put(R.id.button9, new int[] { ToneGenerator.TONE_DTMF_9,
                KeyEvent.KEYCODE_9 });
        DIGITS_BTNS.put(R.id.buttonpound, new int[] {
                ToneGenerator.TONE_DTMF_P, KeyEvent.KEYCODE_POUND });
        DIGITS_BTNS.put(R.id.buttonstar, new int[] { ToneGenerator.TONE_DTMF_S,
                KeyEvent.KEYCODE_STAR });
    };

    private static final SparseArray<String> DIGITS_NAMES = new SparseArray<String>();

    static {
        DIGITS_NAMES.put(R.id.button0, "0");
        DIGITS_NAMES.put(R.id.button1, "1");
        DIGITS_NAMES.put(R.id.button2, "2");
        DIGITS_NAMES.put(R.id.button3, "3");
        DIGITS_NAMES.put(R.id.button4, "4");
        DIGITS_NAMES.put(R.id.button5, "5");
        DIGITS_NAMES.put(R.id.button6, "6");
        DIGITS_NAMES.put(R.id.button7, "7");
        DIGITS_NAMES.put(R.id.button8, "8");
        DIGITS_NAMES.put(R.id.button9, "9");
        DIGITS_NAMES.put(R.id.buttonpound, "pound");
        DIGITS_NAMES.put(R.id.buttonstar, "star");
    };

    public DialpadNovanet(Context context) {
        super(context);
        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.dialpad_novanet, this, true);

    }

    public DialpadNovanet(Context context, AttributeSet attrs) {
        super(context, attrs);
        LayoutInflater inflater = LayoutInflater.from(context);
        inflater.inflate(R.layout.dialpad_novanet, this, true);
    }

    private void dispatchDialKeyEvent(int buttonId) {
        if (onDialKeyListener != null && DIGITS_BTNS.containsKey(buttonId)) {
            int[] datas = DIGITS_BTNS.get(buttonId);
            onDialKeyListener.onTrigger(datas[1], datas[0]);
        }
    }

    @Override
    public void onClick(View v) {
        dispatchDialKeyEvent(v.getId());

    }

    public void setOnDialKeyListener(OnDialKeyListener listener) {
        onDialKeyListener = listener;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        for (int buttonId : DIGITS_BTNS.keySet()) {
            ImageButton button = (ImageButton) findViewById(buttonId);
            if (button != null) {
                button.setOnClickListener(this);
            }
        }

    }

    public interface OnDialKeyListener {

        /**
         * Called when the user make an action
         * 
         * @param keyCode
         *            keyCode pressed
         * @param dialTone
         *            corresponding dialtone
         */
        void onTrigger(int keyCode, int dialTone);
    }

    boolean mForceWidth = false;

    public void setForceWidth(boolean forceWidth) {
        mForceWidth = forceWidth;
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mForceWidth) {
            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
                    getMeasuredHeight());
        }
    };
    /*
     * public void applyTheme(Theme t) {
     * 
     * Log.d(tag, "Theming in progress"); for(int buttonId :
     * DIGITS_BTNS.keySet()) {
     * 
     * ImageButton b = (ImageButton) findViewById(buttonId); // We need to use
     * state list as reused t.applyBackgroundStateListDrawable(b, "btn_dial");
     * 
     * // Src of button Drawable src =
     * t.getDrawableResource("dial_num_"+DIGITS_NAMES.get(buttonId)); if(src !=
     * null) { b.setImageDrawable(src); }
     * 
     * // Padding of button t.applyLayoutMargin(b, "dialpad_btn_margin"); }
     * 
     * }
     */

}

现在创建自定义 EditText

public class DialerEditText extends EditText {

    private static final String tag="DialerEditText";
    private Boolean isDigit=null;
    private Method showSoftInputOnFocus=null;

    public DialerEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
         setIsDigit(true, false);
    }

    public synchronized void setIsDigit(boolean isDigit, boolean autofocus) {
        if(this.isDigit == null || this.isDigit != isDigit) {
            this.isDigit = isDigit;
            reflexSetShowSoftInputOnFocus(!isDigit);
            if (isDigit) {
                setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
                setTextSize(TypedValue.COMPLEX_UNIT_PX, getContext().getResources().getDimension(R.dimen.dialpad_digits_text_size));
            } else {
                setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                        | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
                setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
            }
        }
        applyKeyboardShowHide(autofocus);
    }



    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if(focused) {
            applyKeyboardShowHide(false);
        }else {
            final InputMethodManager imm = ((InputMethodManager) getContext()
                    .getSystemService(Context.INPUT_METHOD_SERVICE));
            if(imm != null && imm.isActive(this)) {
                imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final boolean ret = super.onTouchEvent(event);
        // Must be done after super.onTouchEvent()
        applyKeyboardShowHide(false);
        return ret;
    }

/*
    @Override
    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        boolean ret = false;
        if(!isDigit) {
            ret = super.requestFocus(direction, previouslyFocusedRect);
        }
        applyKeyboardShowHide(false);
        return ret;
    }
*/

    private void applyKeyboardShowHide(boolean autofocus) {
        final InputMethodManager imm = ((InputMethodManager) getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE));
        if (imm != null) {
            if(isDigit) {
                if(imm.isActive(this)) {
                    imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
                }
            }else if(autofocus) {
                imm.showSoftInput(this, 0);
            }
        }
    }

    @Override
    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
            // Since we're replacing the text every time we add or remove a
            // character, only read the difference. (issue 5337550)
            final int added = event.getAddedCount();
            final int removed = event.getRemovedCount();
            final int length = event.getBeforeText().length();
            if (added > removed) {
                event.setRemovedCount(0);
                event.setAddedCount(1);
                event.setFromIndex(length);
            } else if (removed > added) {
                event.setRemovedCount(1);
                event.setAddedCount(0);
                event.setFromIndex(length - 1);
            } else {
                return;
            }
        } else if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
            // The parent EditText class lets tts read "edit box" when this View
            // has a focus, which
            // confuses users on app launch (issue 5275935).
            return;
        }
        super.sendAccessibilityEventUnchecked(event);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        // Here we ensure that we hide the keyboard
        // Since this will be fired when virtual keyboard this will probably
        // blink but for now no better way were found to hide keyboard for sure
        applyKeyboardShowHide(false);
    }

    private void reflexSetShowSoftInputOnFocus(boolean show) {
        if(showSoftInputOnFocus != null) {
            UtilityWrapper.safelyInvokeMethod(showSoftInputOnFocus, this, show);
        }
    }

}

现在您可以将其用作 xml 避免填充和内容,因为那是我的应用程序特定的

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >


        <com.novanet.custom.DialerEditText
            android:id="@+id/edtDialer"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="70" />



    <com.novanet.custom.DialpadNovanet
        android:id="@+id/dial_pad"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_gravity="center_vertical"
        android:layout_weight="65"
        android:paddingBottom="10dip"
        android:paddingLeft="5dip"
        android:paddingRight="5dip" />



</LinearLayout>

现在在你的活动中你可以做到这一点

edtText=(DialerEditText)findViewById(R.id.edtDialer);
        dialPad=(DialpadNovanet)findViewById(R.id.dial_pad);
        dialPad.setOnDialKeyListener(new OnDialKeyListener() {

            @Override
            public void onTrigger(int keyCode, int dialTone) {
                Log.v(tag,"Key "+keyCode);
                KeyEvent event=new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
         edtText.onKeyDown(keyCode, event);

            }
        });
于 2013-04-01T11:48:51.790 回答
0

在清单文件中,在您的活动标签中必须写一个属性,如

android:windowSoftInputMode="stateHidden"

然后它隐藏键盘,直到按下edittext ...

在我的情况下,我在活动标签中使用这样的方式来隐藏软键盘,直到按下编辑文本......

<activity
            android:name="EnglishRadioActivity"
            android:configChanges="orientation"
            android:windowSoftInputMode="stateHidden" >
        </activity>

希望这将解决您的问题快乐编码...

于 2013-04-01T11:29:09.337 回答
0
android:windowSoftInputMode="stateHidden|adjustPan"

将此添加到清单文件中相应的活动名称之后。这将限制默认软键盘出现在您的屏幕上。

于 2013-04-01T11:37:25.913 回答
0

采用android:windowSoftInputMode="stateHidden"

或者 android:windowSoftInputMode="adjustPan"

于 2013-04-01T12:13:01.290 回答