【问题标题】:Android: Handle Back button from custom viewAndroid:从自定义视图处理返回按钮
【发布时间】:2014-05-12 05:42:09
【问题描述】:

我通过扩展RelativeLayout 为我的应用创建了一个自定义视图。通过拖动ImageView,它以dialog 打开。它有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只有在我第二次按下后退按钮后才启动,即在键盘关闭之后。这就是为什么下面的解决方案不起作用的原因。

【问题讨论】:

    标签: android view android-custom-view back-button


    【解决方案1】:

    我终于解决了我的问题,解决方法是使用dispatchKeyEventPreIme。以下是我实际代码中的 sn-p:

    @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);
    }
    

    但实际功劳归this post

    【讨论】:

      【解决方案2】:

      你能不能在你的主要活动中使用 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;
          }
      });
      

      【讨论】:

      • 这个视图将从片段中可见。为了从片段中截取后退按钮,我必须在活动中实现回调,这将导致很多条件和检查。我想避免这种开销,所以我需要在我的自定义视图中拦截后退按钮。它将与后退按钮上的对话框行为相同
      • 好的,你可以在使用edittext时处理关闭键盘的问题吗?并要求关注布局?
      • 我之前试过了。当键盘可见时,按下后退按钮时,键盘会根据需要关闭,但我的覆盖 onKeyDown 的登录没有出现。
      • stackoverflow.com/questions/5113437/… 使用那个,关闭键盘然后专注于“这个”
      • 关闭键盘后如何将焦点转移到我的视图。实际上,我没有看懂代码。为什么在那里使用 onKeyPreIme?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多