我正在尝试使用https://github.com/rockerhieu/emojicon库,以便像WhatsApp和Telegram那样在软键盘上生成EmojiKeyboard。
经过一番研究,我发现他们的做法是通过在软键盘上创建一个Dialog。该库是一个片段,需要在执行时替换布局的某些元素。替换发生在这个类中:
/**
* Class responsible for managin user's interaction with the Emoji Keyboard
*/
public class EmojiKeyboardManager {
public static final String TAG = "EmojiKeyboardManager";
private AppCompatActivity mActivity;
private FrameLayout mEmojiconContainer;
private EmojiconEditText mEditEmojicon;
private LinearLayout mEmojiconButton;
private ImageView mEmojiconButtonImg;
// CONSTRUCTOR
public EmojiKeyboardManager(AppCompatActivity activity) {
this.mActivity = activity;
this.implementEmojiconButton();
this.implementInputTextListener();
//this.initEmojiconFragment(Boolean.FALSE);
}
// INITIALIZATIONS
private void implementEmojiconButton() {
this.mEmojiconButtonImg = (ImageView) this.mActivity.findViewById(R.id.emojiButton);
this.mEmojiconButton = (LinearLayout) this.mActivity.findViewById(R.id.emojiButtonWrapper);
EmojiKeyboardManager.this.mEmojiconButtonImg.setSelected(Boolean.FALSE);
this.mEmojiconButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (EmojiKeyboardManager.this.mEmojiconButtonImg.isSelected()) {
EmojiKeyboardManager.this.hideEmojiconKeyboard(Boolean.TRUE);
} else {
EmojiKeyboardManager.this.showEmojiconKeyboard();
}
}
});
}
public void showEmojiconKeyboard() {
LayoutUtil.dismissSoftKeyboard(this.mEditEmojicon);
EmojiKeyboardManager.this.mEmojiconButtonImg.setImageResource(R.drawable.ic_keyboard_black_36dp);
DialogFragment newFragment = SampleDialogFragment.newInstance();
newFragment.show(this.mActivity.getSupportFragmentManager(), "dialog");
//this.mEmojiconContainer.setVisibility(FrameLayout.VISIBLE);
EmojiKeyboardManager.this.mEmojiconButtonImg.setSelected(Boolean.TRUE);
}
public void hideEmojiconKeyboard(Boolean showSoftkeyboard) {
EmojiKeyboardManager.this.mEmojiconButtonImg.setImageResource(R.drawable.input_emoji);
LayoutUtil.dismissSoftKeyboard(EmojiKeyboardManager.this.mEditEmojicon);
//this.mEmojiconContainer.setVisibility(FrameLayout.GONE);
EmojiKeyboardManager.this.mEmojiconButtonImg.setSelected(Boolean.FALSE);
if (showSoftkeyboard) {
EmojiKeyboardManager.this.mEditEmojicon.requestFocus();
LayoutUtil.showSoftKeyboard(EmojiKeyboardManager.this.mEditEmojicon);
}
}
private void implementInputTextListener() {
this.mEditEmojicon = (EmojiconEditText) this.mActivity.findViewById(R.id.message);
this.mEditEmojicon.clearFocus();
}
// GETTERS AND SETTERS
public EmojiconEditText getmEditEmojicon() {
return this.mEditEmojicon;
}
public Boolean isEmojikeyboardAttached() {
return EmojiKeyboardManager.this.mEmojiconButtonImg.isSelected();
}
}
为了达到我的需要,我正在使用DialogFragment的子类来创建一个像这样的Dialog:
public class SampleDialogFragment extends DialogFragment {
private Dialog dialog;
static SampleDialogFragment newInstance() {
SampleDialogFragment f = new SampleDialogFragment();
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
this.dialog = new Dialog(this.getActivity(), android.R.style.Theme_NoTitleBar);
this.dialog.setContentView(R.layout.rsc_emoji_keyboard);
this.dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
this.dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
this.dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
this.dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
WindowManager.LayoutParams lp = this.dialog.getWindow().getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = (int) App.context().getResources().getDimension(R.dimen.soft_keyboard_min_height);
lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
lp.dimAmount = 0;
return this.dialog;
}
}
我会像那样显示对话:
DialogFragment newFragment = SampleDialogFragment.newInstance();
.show(this.mActivity.getSupportFragmentManager(), "dialog");
Dialog的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<FrameLayout
android:id="@+id/emoji_keyboard"
android:layout_width="match_parent"
android:layout_height="@dimen/soft_keyboard_min_height"/>
</LinearLayout>
FrameLayout应替换为Library Fragment。我在Parent Activity中创建了Dialog并尝试使用了替换Fragment代码,并且还覆盖了DialogFragment的show()方法,但我总是得到一个未找到视图的异常。如何用库片段替换framelayout?
编辑: 跟着它是堆栈跟踪
02-13 22:47:50.613 25553-25606/br.com.instachat.demo D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
02-13 22:47:50.725 25553-25606/br.com.instachat.demo I/Adreno-EGL: <qeglDrvAPI_eglInitialize:379>: EGL 1.4 QUALCOMM build: Nondeterministic_AU_msm8974_LA.BF.1.1.3_RB1__release_AU (I3193f6e94a)
OpenGL ES Shader Compiler Version: E031.28.00.02
Build Date: 10/09/15 Fri
Local Branch: mybranch15039904
Remote Branch: quic/LA.BF.1.1.3_rb1.2
Local Patches: NONE
Reconstruct Branch: NOTHING
02-13 22:47:50.727 25553-25606/br.com.instachat.demo I/OpenGLRenderer: Initialized EGL, version 1.4
02-13 22:47:50.757 25553-25553/br.com.instachat.demo E/RecyclerView: No adapter attached; skipping layout
02-13 22:47:50.791 25553-25623/br.com.instachat.demo I/RegIntentService: br.com.instachat.demo:string/token_received_successfully
02-13 22:47:50.796 25553-25553/br.com.instachat.demo E/RecyclerView: No adapter attached; skipping layout
02-13 22:47:51.395 25553-25553/br.com.instachat.demo I/RegIntentService: br.com.instachat.demo:string/token_sent_to_app_server_successfully
02-13 22:47:51.410 25553-25553/br.com.instachat.demo I/FragmentContacts: br.com.instachat.demo:string/contact_sync_success
02-13 22:47:53.010 25553-25553/br.com.instachat.demo I/FragmentContacts: br.com.instachat.demo:string/get_chatroomid_success
02-13 22:47:53.011 25553-25553/br.com.instachat.demo I/FragmentContacts: chatroom retrieved (via request) has title: Hall 9000
02-13 22:47:53.066 25553-25553/br.com.instachat.demo I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
02-13 22:47:53.440 25553-25606/br.com.instachat.demo D/OpenGLRenderer: endAllActiveAnimators on 0xb82bf2a0 (LinearLayout) with handle 0xb83b6700
02-13 22:47:53.952 25553-25553/br.com.instachat.demo E/FragmentManager: No view found for id 0x7f0d00e3 (br.com.instachat.demo:id/emoji_keyboard) for fragment EmojiconsFragment{d8f31ba #1 id=0x7f0d00e3}
02-13 22:47:53.952 25553-25553/br.com.instachat.demo E/FragmentManager: Activity state:
02-13 22:47:53.953 25553-25553/br.com.instachat.demo D/FragmentManager: Local FragmentActivity a698ff2 State:
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mCreated=truemResumed=true mStopped=false mReallyStopped=false
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mLoadersStarted=true
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: Active Fragments in 6fb086b:
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: #0: SampleDialogFragment{3355fc8 #0 dialog}
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mFragmentId=#0 mContainerId=#0 mTag=dialog
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mState=5 mIndex=0 mWho=android:fragment:0 mBackStackNesting=0
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mAdded=true mRemoving=false mResumed=true mFromLayout=false mInLayout=false
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mRetainInstance=false mRetaining=false mUserVisibleHint=true
02-13 22:47:53.957 25553-25553/br.com.instachat.demo D/FragmentManager: mFragmentManager=FragmentManager{6fb086b in HostCallbacks{d98e861}}
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mHost=android.support.v4.app.FragmentActivity$HostCallbacks@d98e861
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: #1: EmojiconsFragment{d8f31ba #1 id=0x7f0d00e3}
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mFragmentId=#7f0d00e3 mContainerId=#7f0d00e3 mTag=null
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mState=0 mIndex=1 mWho=android:fragment:1 mBackStackNesting=0
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mAdded=true mRemoving=false mResumed=false mFromLayout=false mInLayout=false
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mHidden=false mDetached=false mMenuVisible=true mHasMenu=false
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mRetainInstance=false mRetaining=false mUserVisibleHint=true
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mFragmentManager=FragmentManager{6fb086b in HostCallbacks{d98e861}}
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mHost=android.support.v4.app.FragmentActivity$HostCallbacks@d98e861
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: mArguments=Bundle[{useSystemDefaults=false}]
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: Added Fragments:
02-13 22:47:53.958 25553-25553/br.com.instachat.demo D/FragmentManager: #0: SampleDialogFragment{3355fc8 #0 dialog}
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: #1: EmojiconsFragment{d8f31ba #1 id=0x7f0d00e3}
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: FragmentManager misc state:
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: mHost=android.support.v4.app.FragmentActivity$HostCallbacks@d98e861
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@d98e861
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: mCurState=5 mStateSaved=false mDestroyed=false
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: View Hierarchy:
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: com.android.internal.policy.PhoneWindow$DecorView{f889320 V.ED.... ... 0,0-1080,1920}
02-13 22:47:53.959 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{5a1ae9e V.E..... ... 0,0-1080,1776}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.view.ViewStub{ceeaf86 G.E..... ... 0,0-0,0 #10203ab android:id/action_mode_bar_stub}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.FrameLayout{3b1ca13 V.E..... ... 0,72-1080,1776}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.FitWindowsLinearLayout{bf70450 V.E..... ... 0,0-1080,1704 #7f0d0080 app:id/action_bar_root}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.ViewStubCompat{2bfc047 G.E..... ... 0,0-0,0 #7f0d0081 app:id/action_mode_bar_stub}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.ContentFrameLayout{15d6649 V.E..... ... 0,0-1080,1704 #1020002 android:id/content}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.RelativeLayout{f64fb4e V.E..... ... 0,0-1080,1704 #7f0d0094 app:id/activity_canvas}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.design.widget.AppBarLayout{ee4f46f V.E..... ... 0,0-1080,168 #7f0d0095 app:id/toolbar_wrapper}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.Toolbar{6d0157c V.E..... ... 0,0-1080,168 #7f0d0096 app:id/toolbar}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.RelativeLayout{c997e5a V.E..... ... 168,0-528,168}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: com.mikhaellopez.circularimageview.CircularImageView{d196b08 V.ED.... ... 0,15-135,152 #7f0d0097 app:id/thumbnail}
02-13 22:47:53.962 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{576688b V.E..... ... 150,27-360,141}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.AppCompatTextView{dc70d68 V.ED.... ... 0,0-210,65 #7f0d0098 app:id/name}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.AppCompatTextView{a469581 V.ED.... ... 0,65-99,114 #7f0d0099 app:id/status}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.ImageButton{70d1e05 VFED..C. ... 0,0-168,168}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.ActionMenuView{48ca098 V.E..... ... 816,0-1080,168}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.view.menu.ActionMenuItemView{e995357 VFED..CL ... 0,12-144,156 #7f0d00f2 app:id/action_attach_media}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.ActionMenuPresenter$OverflowMenuButton{41af862 VFED..C. ... 144,12-264,156}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.RecyclerView{4612626 VFE..... F.. 0,168-1080,1506 #7f0d009a app:id/messages}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{e610267 V.E..... ... 0,1506-1080,1704 #7f0d009b app:id/bottomLayoutWrapper}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{b39814 V.E..... ... 24,24-1056,174}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{84608bd V.E..... ... 0,0-882,150}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{ba97eb2 V.E...C. ... 1,0-145,150 #7f0d00da app:id/emojiButtonWrapper}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.AppCompatImageView{b715e03 V.ED.... .S. 36,39-108,111 #7f0d00db app:id/emojiButton}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: com.rockerhieu.emojicon.EmojiconEditText{33c2180 VFED..CL ... 145,0-822,150 #7f0d00b7 app:id/message}
02-13 22:47:53.963 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{bcf73b9 V.E..... ... 822,38-822,111}
02-13 22:47:53.964 25553-25553/br.com.instachat.demo D/FragmentManager: android.widget.LinearLayout{624b074 VFE..... ... 0,0-0,0}
02-13 22:47:53.964 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.AppCompatAutoCompleteTextView{6acd3fe VFED..CL ... 0,0-0,73 #7f0d00ec app:id/autotext}
02-13 22:47:53.964 25553-25553/br.com.instachat.demo D/FragmentManager: android.support.v7.widget.AppCompatImageButton{4a1d75f VFED..C. ... 882,0-1032,150 #7f0d00dc app:id/send}
02-13 22:47:53.964 25553-25553/br.com.instachat.demo D/FragmentManager: android.view.View{e881223 V.ED.... ... 0,1776-1080,1920 #1020030 android:id/navigationBarBackground}
02-13 22:47:53.964 25553-25553/br.com.instachat.demo D/FragmentManager: android.view.View{4ba94d9 V.ED.... ... 0,0-1080,72 #102002f android:id/statusBarBackground}
02-13 22:47:53.964 25553-25553/br.com.instachat.demo D/AndroidRuntime: Shutting down VM
02-13 22:47:53.968 25553-25553/br.com.instachat.demo E/AndroidRuntime: FATAL EXCEPTION: main
Process: br.com.instachat.demo, PID: 25553
java.lang.IllegalArgumentException: No view found for id 0x7f0d00e3 (br.com.instachat.demo:id/emoji_keyboard) for fragment EmojiconsFragment{d8f31ba #1 id=0x7f0d00e3}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1059)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:746)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
解决
我可以使用以下代码管理问题:
public class SampleDialogFragment extends DialogFragment {
static SampleDialogFragment newInstance() {
SampleDialogFragment f = new SampleDialogFragment();
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_NoTitleBar);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.rsc_emoji_keyboard, container, false);
this.getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
this.getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
this.getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
this.getDialog().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
WindowManager.LayoutParams lp = this.getDialog().getWindow().getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = (int) App.context().getResources().getDimension(R.dimen.soft_keyboard_min_height);
lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
lp.dimAmount = 0;
getChildFragmentManager()
.beginTransaction()
.replace(R.id.emoji_keyboard, EmojiconsFragment.newInstance(false))
.commit();
return v;
}
}