Android:如何从自定义视图中处理返回按钮

8
我通过扩展RelativeLayout创建了一个自定义视图用于我的应用程序。它作为dialog打开,通过拖动一个ImageView。它有EditTextsButtons。我重写了我的视图中的onKeyDown,因为我需要拦截这个视图中的返回按钮。如果自定义视图可见,edittext没有获得焦点,如果我按下返回按钮,视图将被取消,这是期望的。
问题出现在edittext获得焦点并且键盘可见时,按下返回按钮后,软键盘将被取消,但是如果我再次按下返回按钮,那么不会取消自定义视图,而是调用了super.onKeyDown(),我将退出我的应用程序,而期望的功能是在软键盘消失后取消视图。我做错了什么?
以下是我的自定义视图代码:
public class AddTransactionView extends RelativeLayout implements View.OnClickListener {
    private final String TAG = "AddTransactionView";

    private Context context;

    private ViewGroup parentView;

    private FriendsDAO mFriendsDAO;

    private AppPreference mAppPreference;

    private ImageLoader imageLoader;

    private DisplayImageOptions options;

    private CircularImageView friendsImage;

    private Button btnIOwe, btnTheyOwe;

    private EditText edtTransactionDesc, edtTransactionAmt;

    private RelativeLayout relAddTransaction;

    private int status;

    public AddTransactionView(Context context, View anchorView, int marginTop,
        ViewGroup parentView, FriendsDAO mFriendsDAO) {
        super(context);
        Log.e(TAG, "AddTransactionView constructor");
        this.context = context;
        this.parentView = parentView;
        this.mFriendsDAO = mFriendsDAO;
        doInitialization();
        LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.add_transaction_popup, this);

        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT,
            RelativeLayout.LayoutParams.MATCH_PARENT);

        params.addRule(RelativeLayout.ABOVE, anchorView.getId());
        params.setMargins(0, marginTop, 0, 0);
        view.setLayoutParams(params);
        this.setFocusableInTouchMode(true);
        this.requestFocus();
        parentView.addView(this);
        initializeView(view, mFriendsDAO);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.e(TAG, "onKeyCodeDown");
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Log.e(TAG, "onKeyCodeDown if");
            Log.e(TAG, "onKeyCodeDown else");
            dismiss();
            return true;
        } else {
            Log.e(TAG, "onKeyCodeDown default");
            return super.onKeyDown(keyCode, event);
        }
    }

    private void dismiss() {
        parentView.removeView(this);
    }
}

PS: 由于我的应用程序设计限制,我没有使用对话框或弹出窗口。

更新1

当键盘关闭时,焦点不会回到我的自定义视图。我尝试了下面建议的答案,但我发现在Android中键盘关闭时不会发送IME事件。有没有其他方法在键盘关闭后将焦点返回到我的视图上?

更新2 刚才,我发现EditText的onKeyListener只在我第二次按下返回按钮后触发,也就是在键盘关闭后。这就是为什么下面的解决方案不起作用的原因。

2个回答

15

我终于解决了我的问题,解决方案是使用dispatchKeyEventPreIme。以下是我的实际代码片段:

@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
    Log.e(TAG, "dispatchKeyEventPreIme(" + event + ")");
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        KeyEvent.DispatcherState state = getKeyDispatcherState();
        if (state != null) {
            Log.e(TAG, "dispatchKeyEventPreIme state != null");
            if (event.getAction() == KeyEvent.ACTION_DOWN
                    && event.getRepeatCount() == 0) {
                Log.e(TAG, "dispatchKeyEventPreIme ACTION_DOWN");
                state.startTracking(event, this);
                return true;
            } else if (event.getAction() == KeyEvent.ACTION_UP
                    && !event.isCanceled() && state.isTracking(event)) {
                Log.e(TAG, "dispatchKeyEventPreIme ACTION_UP");
                if (edtTransactionAmt.hasFocus()
                        || edtTransactionDesc.hasFocus()) {
                    Log.e(TAG, "dispatchKeyEventPreIme edittext has focus");
                    AppUtils.hideSoftKeyboard(context, edtTransactionAmt);
                    edtTransactionAmt.clearFocus();
                    edtTransactionDesc.clearFocus();
                } else {
                    Log.e(TAG, "dispatchKeyEventPreIme dismiss view");
                    dismiss();
                }
                return true;
            }
        }
    }

    return super.dispatchKeyEventPreIme(event);
}

但实际的功劳归于这篇帖子


-1

你的主活动中不能使用onbackpress吗?

if (myAddTransactionView.getVisibility == LinearLayout.VISIBLE) {
     myAddTransactionView.dismiss();
} else {
   Super.....

或者在您的编辑文本上

edtTransactionDesc.setOnKeyListener(new OnKeyListener()
{
    public boolean onKey(View v, int keyCode, KeyEvent event)
    {
        if (event.getAction() == KeyEvent.ACTION_DOWN)
        {
            //check if the right key was pressed
            if (keyCode == KeyEvent.KEYCODE_BACK)
            {
                InputMethodManager imm = (InputMethodManager)getSystemService(
                 Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(edtTransactionDesc.getWindowToken(), 0);
                AddTransactionView.this.requestFocus(); 
                return false;
            }
        }
        return true;
    }
});

这个视图将从片段中可见。为了从片段中拦截返回按钮,我必须在活动中实现回调,这将导致很多条件和检查。我想避免这种开销,所以我需要在我的自定义视图中拦截返回按钮。它将与对话框在返回按钮上的行为相同。 - Nitish
好的,您能处理在使用EditText时按下返回键关闭键盘并在布局上请求焦点吗? - RuAware
我之前试过了。当键盘可见时,按下返回按钮,键盘会按预期消失,但是在我的重写的onKeyDown方法中,日志没有显示出来。 - Nitish
使用它,关闭键盘,然后聚焦于“this”。 - RuAware
刚刚编辑了我的帖子。它被调用了,但只有在我第二次按返回按钮后才出现。 - Nitish
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接