stop using PopupWindow for emoji. too many android bugs.

Closes #3655
// FREEBIE
This commit is contained in:
Jake McGinty 2015-07-13 15:45:14 -07:00 committed by Moxie Marlinspike
parent c7599094f5
commit b519fd2533
7 changed files with 85 additions and 114 deletions

View file

@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/quick_attachment_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black">
<org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout
android:id="@+id/layout_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
@ -159,6 +159,11 @@
</LinearLayout>
</RelativeLayout>
</org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer>
<ViewStub android:id="@+id/emoji_drawer_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inflatedId="@+id/emoji_drawer"
android:layout="@layout/emoji_drawer_stub" />
</org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout>
</org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer>

View file

@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout android:background="?emoji_tab_strip_background"
android:orientation="horizontal"
@ -47,4 +43,4 @@
android:layout_height="match_parent"
android:background="?emoji_background" />
</LinearLayout>
</merge>

View file

@ -49,6 +49,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.view.ViewStub;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
@ -68,13 +69,12 @@ import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout;
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener;
import org.thoughtcrime.securesms.components.SendButton;
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiEventListener;
import org.thoughtcrime.securesms.components.emoji.EmojiPopup;
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
import org.thoughtcrime.securesms.components.camera.HidingImageButton;
import org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer.AttachmentDrawerListener;
import org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer.DrawerState;
import org.thoughtcrime.securesms.components.camera.QuickAttachmentDrawer;
import org.thoughtcrime.securesms.crypto.MasterCipher;
import org.thoughtcrime.securesms.crypto.MasterSecret;
@ -178,7 +178,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private AttachmentManager attachmentManager;
private BroadcastReceiver securityUpdateReceiver;
private BroadcastReceiver groupUpdateReceiver;
private Optional<EmojiPopup> emojiPopup = Optional.absent();
private Optional<EmojiDrawer> emojiDrawer = Optional.absent();
private EmojiToggle emojiToggle;
protected HidingImageButton quickAttachmentToggle;
private QuickAttachmentDrawer quickAttachmentDrawer;
@ -267,7 +267,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
quickAttachmentDrawer.onConfigurationChanged();
hideEmojiPopup(false);
hideEmojiDrawer(false);
}
@Override
@ -276,7 +276,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (recipients != null) recipients.removeListener(this);
if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver);
if (groupUpdateReceiver != null) unregisterReceiver(groupUpdateReceiver);
if (isEmojiDrawerOpen()) hideEmojiPopup(false);
if (isEmojiDrawerOpen()) hideEmojiDrawer(false);
super.onDestroy();
}
@ -384,8 +384,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onBackPressed() {
Log.w(TAG, "onBackPressed()");
if (isEmojiDrawerOpen()) {
hideEmojiPopup(false);
Log.w(TAG, "hiding emoji popup");
hideEmojiDrawer(false);
} else if (quickAttachmentDrawer.isOpen()) {
quickAttachmentDrawer.close();
} else {
@ -395,7 +397,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onKeyboardShown() {
hideEmojiPopup(true);
hideEmojiDrawer(true);
}
//////// Event Handlers
@ -866,10 +868,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
private EmojiPopup getEmojiPopup() {
if (!emojiPopup.isPresent()) {
EmojiPopup emojiPopup = new EmojiPopup(container);
emojiPopup.setEmojiEventListener(new EmojiEventListener() {
private EmojiDrawer getEmojiDrawer() {
if (!emojiDrawer.isPresent()) {
EmojiDrawer emojiDrawer = (EmojiDrawer)((ViewStub)findViewById(R.id.emoji_drawer_stub)).inflate();
emojiDrawer.setEmojiEventListener(new EmojiEventListener() {
@Override public void onKeyEvent(KeyEvent keyEvent) {
composeText.dispatchKeyEvent(keyEvent);
}
@ -879,28 +881,33 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
composeText.insertEmoji(emoji);
}
});
this.emojiPopup = Optional.of(emojiPopup);
this.emojiDrawer = Optional.of(emojiDrawer);
}
return emojiPopup.get();
return emojiDrawer.get();
}
private void showEmojiPopup() {
getEmojiPopup().show();
private void showEmojiDrawer() {
getEmojiDrawer().show(container);
emojiToggle.setToIme();
}
protected void hideEmojiPopup(boolean expectingKeyboard) {
protected void hideEmojiDrawer(boolean expectingKeyboard) {
if (isEmojiDrawerOpen()) {
getEmojiPopup().dismiss();
if (!expectingKeyboard || container.isLandscape()) {
container.unpadForCustomKeyboard();
getEmojiDrawer().dismiss();
} else {
container.postOnKeyboardOpen(new Runnable() {
@Override public void run() {
getEmojiDrawer().dismiss();
}
});
}
}
emojiToggle.setToEmoji();
}
private boolean isEmojiDrawerOpen() {
return emojiPopup.isPresent() && emojiPopup.get().isShowing();
return emojiDrawer.isPresent() && emojiDrawer.get().isShowing();
}
private void initializeResources() {
@ -1358,12 +1365,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public void onClick(View v) {
Log.w(TAG, "EmojiToggleListener onClick()");
if (isEmojiDrawerOpen()) {
hideEmojiPopup(true);
hideEmojiDrawer(true);
openKeyboardForComposition();
} else {
container.postOnKeyboardClose(new Runnable() {
@Override public void run() {
showEmojiPopup();
showEmojiDrawer();
}
});
quickAttachmentDrawer.close();
@ -1378,7 +1385,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
InputMethodManager input = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
input.hideSoftInputFromWindow(composeText.getWindowToken(), 0);
composeText.clearFocus();
hideEmojiPopup(false);
hideEmojiDrawer(false);
quickAttachmentDrawer.open();
}
}
@ -1426,7 +1433,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onClick(View v) {
hideEmojiPopup(true);
hideEmojiDrawer(true);
}
@Override
@ -1454,7 +1461,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus && isEmojiDrawerOpen()) {
hideEmojiPopup(true);
hideEmojiDrawer(true);
} else if (hasFocus && quickAttachmentDrawer.isOpen()) {
quickAttachmentDrawer.close();
}

View file

@ -114,8 +114,8 @@ public class ConversationPopupActivity extends ConversationActivity {
}
@Override
protected void hideEmojiPopup(boolean expectingKeyboard) {
super.hideEmojiPopup(false);
protected void hideEmojiDrawer(boolean expectingKeyboard) {
super.hideEmojiDrawer(false);
}
@Override

View file

@ -97,14 +97,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
oldRect.set(newRect);
}
public void padForCustomKeyboard(final int height) {
setPadding(0, 0, 0, height);
}
public void unpadForCustomKeyboard() {
setPadding(0, 0, 0, 0);
}
private int getViewInset() {
if (Build.VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
return 0;
@ -135,7 +127,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
setKeyboardPortraitHeight(keyboardHeight);
}
notifyShownListeners();
unpadForCustomKeyboard();
}
protected void onKeyboardClose() {
@ -188,6 +179,19 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
}
}
public void postOnKeyboardOpen(final Runnable runnable) {
if (!keyboardOpen) {
addOnKeyboardShownListener(new OnKeyboardShownListener() {
@Override public void onKeyboardShown() {
removeOnKeyboardShownListener(this);
runnable.run();
}
});
} else {
runnable.run();
}
}
public void addOnKeyboardHiddenListener(OnKeyboardHiddenListener listener) {
hiddenListeners.add(listener);
}
@ -205,13 +209,15 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
}
private void notifyHiddenListeners() {
for (OnKeyboardHiddenListener listener : hiddenListeners) {
final Set<OnKeyboardHiddenListener> listeners = new HashSet<>(hiddenListeners);
for (OnKeyboardHiddenListener listener : listeners) {
listener.onKeyboardHidden();
}
}
private void notifyShownListeners() {
for (OnKeyboardShownListener listener : shownListeners) {
final Set<OnKeyboardShownListener> listeners = new HashSet<>(shownListeners);
for (OnKeyboardShownListener listener : listeners) {
listener.onKeyboardShown();
}
}

View file

@ -5,7 +5,6 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.LinearLayoutCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
@ -19,6 +18,7 @@ import android.widget.LinearLayout;
import com.astuetz.PagerSlidingTabStrip;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout;
import org.thoughtcrime.securesms.components.RepeatableImageKey;
import org.thoughtcrime.securesms.components.RepeatableImageKey.KeyEventListener;
import org.thoughtcrime.securesms.components.emoji.EmojiPageView.EmojiSelectionListener;
@ -27,10 +27,9 @@ import org.thoughtcrime.securesms.util.ResUtil;
import java.util.LinkedList;
import java.util.List;
public class EmojiDrawer extends LinearLayoutCompat {
public class EmojiDrawer extends LinearLayout {
private static final KeyEvent DELETE_KEY_EVENT = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL);
private LinearLayout container;
private ViewPager pager;
private List<EmojiPageModel> models;
private PagerSlidingTabStrip strip;
@ -42,11 +41,8 @@ public class EmojiDrawer extends LinearLayoutCompat {
}
public EmojiDrawer(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EmojiDrawer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
super(context, attrs);
setOrientation(VERTICAL);
final View v = LayoutInflater.from(getContext()).inflate(R.layout.emoji_drawer, this, true);
initializeResources(v);
initializePageModels();
@ -59,7 +55,6 @@ public class EmojiDrawer extends LinearLayoutCompat {
private void initializeResources(View v) {
Log.w("EmojiDrawer", "initializeResources()");
this.container = (LinearLayout) v.findViewById(R.id.container);
this.pager = (ViewPager) v.findViewById(R.id.emoji_pager);
this.strip = (PagerSlidingTabStrip) v.findViewById(R.id.tabs);
@ -71,8 +66,19 @@ public class EmojiDrawer extends LinearLayoutCompat {
});
}
public boolean isOpen() {
return container.getVisibility() == View.VISIBLE;
public boolean isShowing() {
return getVisibility() == VISIBLE;
}
public void show(KeyboardAwareLinearLayout container) {
ViewGroup.LayoutParams params = getLayoutParams();
params.height = container.getKeyboardHeight();
setLayoutParams(params);
setVisibility(VISIBLE);
}
public void dismiss() {
setVisibility(GONE);
}
private void initializeEmojiGrid() {

View file

@ -1,49 +0,0 @@
package org.thoughtcrime.securesms.components.emoji;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.PopupWindow;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout;
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiEventListener;
public class EmojiPopup extends PopupWindow {
private static final String TAG = EmojiPopup.class.getSimpleName();
private KeyboardAwareLinearLayout parent;
public EmojiPopup(KeyboardAwareLinearLayout parent) {
super(new EmojiDrawer(parent.getContext()),
parent.getWidth(),
parent.getResources().getDimensionPixelSize(R.dimen.min_emoji_drawer_height));
this.parent = parent;
getContentView().setClickable(true);
getContentView().setFocusableInTouchMode(true);
getContentView().setFocusable(true);
setTouchable(true);
setFocusable(true);
}
public void setEmojiEventListener(EmojiEventListener listener) {
((EmojiDrawer)getContentView()).setEmojiEventListener(listener);
}
public void show() {
setHeight(parent.getKeyboardHeight());
setWidth(parent.getWidth());
parent.padForCustomKeyboard(getHeight());
Log.w(TAG, String.format("show(%d, %d)", getWidth(), getHeight()));
showAtLocation(parent, Gravity.BOTTOM | Gravity.LEFT, 0, 0);
}
@Override
public void dismiss() {
super.dismiss();
}
public void update() {
update(parent, 0, 0, parent.getWidth(), -1);
}
}