Jacksgong / JKeyboardPanelSwitch

For resolve the layout conflict when keybord & panel are switching (Android键盘面板冲突 布局闪动处理方案)
Apache License 2.0
4.18k stars 684 forks source link

不支持从一个Activity跳到聊天框时直接打开键盘或者表情? #4

Closed coolegos closed 8 years ago

Jacksgong commented 8 years ago

我不是很明白你的意思。从字面上理解,这个并不属于这个组件的范畴,这个组件只是为了解决,键盘面板跳动布局闪动的问题。

coolegos commented 8 years ago

@Jacksgong 我只是试了试,进去的时候直接实现PanelLayout,但是我setVisibility(VISIBLE),似乎打不开。

Jacksgong commented 8 years ago

并不存在这个问题的。我这边也无法复现(你可以在JChattingActivity#onCreate中的assignViews()之后,直接调用mPanelRoot.setVisibility(View.VISIBLE))。如果你那边始终有这个问题。麻烦将相关代码push到你的git,我给你定位下看看问题在哪里。

Jacksgong commented 8 years ago

请参考demo中的JChattingActivity

如果你需要进入JChattingActivity立马显示键盘,只需要做如下修改:

在demo的AndroidManifest.xml上将:

<activity
  android:name=".activity.JChattingActivity"
  android:label="@string/activity_jchatting_title"
  android:windowSoftInputMode="adjustResize" />

修改为:

<activity
  android:name=".activity.JChattingActivity"
  android:label="@string/activity_jchatting_title"
  android:windowSoftInputMode="adjustResize|stateVisible" />

如果你希望进入JChattingActivity立马显示面板,只需要做如下修改:

打开JChattingActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chatting);

    assignViews();

    // 这里增加了一句使进入聊天的时候默认打开面板
    mPanelRoot.setVisibility(View.VISIBLE);

    mContentRyv.setLayoutManager(new LinearLayoutManager(this));

    mContentRyv.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
                KeyboardUtil.hideKeyboard(mSendEdt);
                mPanelRoot.setVisibility(View.GONE);
            }

            return false;
        }
    });
}
Jacksgong commented 8 years ago

其他操作可以参看README中的:

// Keyboard与面板相互切换
public void switchPanel(){
    if (mPanelLayout.getVisibility() == View.VISIBLE){
        KeyboardUtil.showKeyboard(mSendEdt);
    } else {
        KeyboardUtil.hideKeyboard(mSendEdt);
        showPanel()
    }
}

// 隐藏面板
public void hidePanel(){
    mPanelLayout.setVisibility(View.GONE);
}

// 显示面板
public void showPanel(){
    mPanelLayout.setVisibility(View.VISIBLE);
}
Jacksgong commented 8 years ago

@38017032 你可以参看我上面给出来的方案,先在demo上试试看。

coolegos commented 8 years ago
button.setOnClickListener(new OnClickListener()
{

    @Override
    public void onClick(View v)
    {
        final Dialog dialog = new Dialog(JChattingActivity.this, R.style.commetn_reply_dialog_style);
        final ViewGroup contentView = (ViewGroup) LayoutInflater.from(JChattingActivity.this).inflate(
                        R.layout.activity_chatting, null);
        dialog.setContentView(contentView);
        dialog.setCanceledOnTouchOutside(true);
        dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        dialog.show();

        ImageView plusIv = (ImageView) contentView.findViewById(R.id.plus_iv);

        final PanelLayout mPanelRoot = (PanelLayout) contentView.findViewById(R.id.panel_root);
        final EditText mSendEdt = (EditText) contentView.findViewById(R.id.send_edt);

        mPanelRoot.setVisibility(View.VISIBLE); // 应该是我这里写的有问题

        plusIv.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {

                if (mPanelRoot.getVisibility() == View.VISIBLE)
                {
                    KeyboardUtil.showKeyboard(mSendEdt);
                }
                else
                {
                    KeyboardUtil.hideKeyboard(mSendEdt);
                    mPanelRoot.setVisibility(View.VISIBLE);
                }
            }
        });

        contentView.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                dialog.dismiss();
            }
        });
    }
});

我是写在了Dialog中。在你的JChattingActivity改了下

Jacksgong commented 8 years ago

恩。问题找到了吗。如果始终无法找到,可以考虑直接将你改了的项目push的github或者发邮件给我(igzhenjie@gmail.com),我给你定位下。

coolegos commented 8 years ago

@Jacksgong 昨天打的一个邮件发现被拦截了。https://github.com/38017032/JKeyboardPanelSwitch

Jacksgong commented 8 years ago

好的。我拉下来看下。

Jacksgong commented 8 years ago

@38017032 最简单的解决方案是,在onClick的时候:

将这个:

mPanelRoot.setVisibility(View.VISIBLE);

修改为:

mPanelRoot.post(new Runnable() {
    @Override
    public void run() {
        mPanelRoot.setVisibility(View.VISIBLE); // 应该是我这里写的有问题
    }
});
coolegos commented 8 years ago

好的 谢谢了 ,我之前是这样做的

new Handler().postDelayed(new Runnable()
            {

                @Override
                public void run()
                {
                    KeyboardUtil.hideKeyboard(replyEdit);
                    mPanelRoot.setVisibility(View.VISIBLE);
                }
            }, 100);

界面会感觉明显在最下面停顿一下然后再打开。

Jacksgong commented 8 years ago

最根本的原因是:

dialog 使用的背景是透明的(windowIsTranslucent=true),而默认status bar是显示的,背景后面的activity不是full screen。因为如此dialog在onMeasure的时候,第一次measure的时候还没attach上status barCustomRootLayout高度为customHeight + statusBarHeight,而第二次measure的时候attach上了status barCustomRootLayout的高度变为了customHeight了,由于我们的机制识别到高度减少了,误以为是键盘起来了,因此开始处理对应的事情,因此就出现了你之前的那个情况。


为什么我们的临时方案可以解决这个问题呢(确实有可能停顿下):

因为View的布局变化通知最终也是通过Looper触发的,而我们使用抛事件的形式,而View的布局变化使用了往Looper的MessageQueue中插入了一个barrier,并且执行布局变化,我们的事件就被放到了布局变化完成了之后处理,因此就避开了那个问题。


最终解决方法:

我接下来会提一个commit来从根本上解决你的这个问题。

Jacksgong commented 8 years ago

@38017032 你rebase我最新的代码,或者参考这个diff修改下,直接setVisibility(View.VISIBLE) (不用抛Message)就可以解决了,也不会有停顿的问题。

coolegos commented 8 years ago

@Jacksgong 非常谢谢你啊 ,这么晚才来。按照你的修改确实是可以的。

Jacksgong commented 8 years ago

:)