From 62ca083a9cf9690570d4abac37b60d2c8c64ffdd Mon Sep 17 00:00:00 2001 From: Ankush Sachdeva Date: Tue, 2 Sep 2014 02:51:57 +0530 Subject: inital commit --- .../ankushsachdeva/emojicon/EmojiconsPopup.java | 373 +++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 src/github/ankushsachdeva/emojicon/EmojiconsPopup.java (limited to 'src/github/ankushsachdeva/emojicon/EmojiconsPopup.java') diff --git a/src/github/ankushsachdeva/emojicon/EmojiconsPopup.java b/src/github/ankushsachdeva/emojicon/EmojiconsPopup.java new file mode 100644 index 0000000..f6c0fbd --- /dev/null +++ b/src/github/ankushsachdeva/emojicon/EmojiconsPopup.java @@ -0,0 +1,373 @@ +/* + * Copyright 2014 Ankush Sachdeva + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package github.ankushsachdeva.emojicon; + +import github.ankushsachdeva.emojicon.EmojiconGridView.OnEmojiconClickedListener; +import github.ankushsachdeva.emojicon.emoji.Emojicon; +import github.ankushsachdeva.emojicon.emoji.Nature; +import github.ankushsachdeva.emojicon.emoji.Objects; +import github.ankushsachdeva.emojicon.emoji.People; +import github.ankushsachdeva.emojicon.emoji.Places; +import github.ankushsachdeva.emojicon.emoji.Symbols; + +import java.util.Arrays; +import java.util.List; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Rect; +import android.os.Handler; +import android.os.SystemClock; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewPager; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.view.WindowManager.LayoutParams; +import android.widget.EditText; +import android.widget.PopupWindow; + +import github.ankushsachdeva.emojicon.R; + + +/** + * @author Ankush Sachdeva (sankush@yahoo.co.in). + */ + +public class EmojiconsPopup extends PopupWindow implements ViewPager.OnPageChangeListener, EmojiconRecents { + private int mEmojiTabLastSelectedIndex = -1; + private View[] mEmojiTabs; + private PagerAdapter mEmojisAdapter; + private EmojiconRecentsManager mRecentsManager; + private int keyBoardHeight = 0; + private Boolean isOpened = false; + OnEmojiconClickedListener onEmojiconClickedListener; + OnEmojiconBackspaceClickedListener onEmojiconBackspaceClickedListener; + OnSoftKeyboardOpenCloseListener onSoftKeyboardOpenCloseListener; + View rootView; + Context mContext; + + public ViewPager emojisPager; + + public EmojiconsPopup(View rootView, Context mContext){ + super(mContext); + this.mContext = mContext; + this.rootView = rootView; + View customView = createCustomView(); + setContentView(customView); + + setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); + //default size + setSize((int) mContext.getResources().getDimension(R.dimen.keyboard_height), LayoutParams.MATCH_PARENT); + } + + public void setOnSoftKeyboardOpenCloseListener(OnSoftKeyboardOpenCloseListener listener){ + this.onSoftKeyboardOpenCloseListener = listener; + } + + public void setOnEmojiconClickedListener(OnEmojiconClickedListener listener){ + this.onEmojiconClickedListener = listener; + } + + public void setOnEmojiconBackspaceClickedListener(OnEmojiconBackspaceClickedListener listener){ + this.onEmojiconBackspaceClickedListener = listener; + } + + public void showAtBottom(){ + showAtLocation(rootView, Gravity.BOTTOM, 0, 0); + } + + public Boolean isKeyBoardOpen(){ + return isOpened; + } + + public void setSizeForSoftKeyboard(){ + rootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + Rect r = new Rect(); + rootView.getWindowVisibleDisplayFrame(r); + + int screenHeight = rootView.getRootView() + .getHeight(); + int heightDifference = screenHeight + - (r.bottom - r.top); + int resourceId = mContext.getResources() + .getIdentifier("status_bar_height", + "dimen", "android"); + if (resourceId > 0) { + heightDifference -= mContext.getResources() + .getDimensionPixelSize(resourceId); + } + if (heightDifference > 100) { + keyBoardHeight = heightDifference; + setSize(LayoutParams.MATCH_PARENT, keyBoardHeight); + if(isOpened == false){ + if(onSoftKeyboardOpenCloseListener!=null) + onSoftKeyboardOpenCloseListener.onKeyboardOpen(keyBoardHeight); + } + isOpened = true; + } + else{ + isOpened = false; + if(onSoftKeyboardOpenCloseListener!=null) + onSoftKeyboardOpenCloseListener.onKeyboardClose(); + } + } + }); + } + + public void setSize(int width, int height){ + setWidth(width); + setHeight(height); + } + + public View createCustomView() { + LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.emojicons, null, false); + emojisPager = (ViewPager) view.findViewById(R.id.emojis_pager); + emojisPager.setOnPageChangeListener(this); + EmojiconRecents recents = this; + mEmojisAdapter = new EmojisPagerAdapter( + Arrays.asList( + new EmojiconRecentsGridView(mContext, null, null, this), + new EmojiconGridView(mContext, People.DATA, recents, this), + new EmojiconGridView(mContext, Nature.DATA, recents, this), + new EmojiconGridView(mContext, Objects.DATA, recents, this), + new EmojiconGridView(mContext, Places.DATA, recents, this), + new EmojiconGridView(mContext, Symbols.DATA, recents, this) + ) + ); + emojisPager.setAdapter(mEmojisAdapter); + mEmojiTabs = new View[6]; + mEmojiTabs[0] = view.findViewById(R.id.emojis_tab_0_recents); + mEmojiTabs[1] = view.findViewById(R.id.emojis_tab_1_people); + mEmojiTabs[2] = view.findViewById(R.id.emojis_tab_2_nature); + mEmojiTabs[3] = view.findViewById(R.id.emojis_tab_3_objects); + mEmojiTabs[4] = view.findViewById(R.id.emojis_tab_4_cars); + mEmojiTabs[5] = view.findViewById(R.id.emojis_tab_5_punctuation); + for (int i = 0; i < mEmojiTabs.length; i++) { + final int position = i; + mEmojiTabs[i].setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + emojisPager.setCurrentItem(position); + } + }); + } + view.findViewById(R.id.emojis_backspace).setOnTouchListener(new RepeatListener(1000, 50, new OnClickListener() { + + @Override + public void onClick(View v) { + if(onEmojiconBackspaceClickedListener != null) + onEmojiconBackspaceClickedListener.onEmojiconBackspaceClicked(v); + } + })); + + // get last selected page + mRecentsManager = EmojiconRecentsManager.getInstance(view.getContext()); + int page = mRecentsManager.getRecentPage(); + // last page was recents, check if there are recents to use + // if none was found, go to page 1 + if (page == 0 && mRecentsManager.size() == 0) { + page = 1; + } + + if (page == 0) { + onPageSelected(page); + } + else { + emojisPager.setCurrentItem(page, false); + } + return view; + } + + public static void input(EditText editText, Emojicon emojicon) { + if (editText == null || emojicon == null) { + return; + } + + int start = editText.getSelectionStart(); + int end = editText.getSelectionEnd(); + if (start < 0) { + editText.append(emojicon.getEmoji()); + } else { + editText.getText().replace(Math.min(start, end), Math.max(start, end), emojicon.getEmoji(), 0, emojicon.getEmoji().length()); + } + } + + @Override + public void addRecentEmoji(Context context, Emojicon emojicon) { + EmojiconRecentsGridView fragment = ((EmojisPagerAdapter)emojisPager.getAdapter()).getRecentFragment(); + fragment.addRecentEmoji(context, emojicon); + } + + public static void backspace(EditText editText) { + KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL); + editText.dispatchKeyEvent(event); + } + + @Override + public void onPageScrolled(int i, float v, int i2) { + } + + @Override + public void onPageSelected(int i) { + if (mEmojiTabLastSelectedIndex == i) { + return; + } + switch (i) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + if (mEmojiTabLastSelectedIndex >= 0 && mEmojiTabLastSelectedIndex < mEmojiTabs.length) { + mEmojiTabs[mEmojiTabLastSelectedIndex].setSelected(false); + } + mEmojiTabs[i].setSelected(true); + mEmojiTabLastSelectedIndex = i; + mRecentsManager.setRecentPage(i); + break; + } + } + + @Override + public void onPageScrollStateChanged(int i) { + } + + private static class EmojisPagerAdapter extends PagerAdapter { + private List views; + public EmojiconRecentsGridView getRecentFragment(){ + for (EmojiconGridView it : views) { + if(it instanceof EmojiconRecentsGridView) + return (EmojiconRecentsGridView)it; + } + return null; + } + public EmojisPagerAdapter(List views) { + super(); + this.views = views; + } + + @Override + public int getCount() { + return views.size(); + } + + + @Override + public Object instantiateItem(ViewGroup container, int position) { + View v = views.get(position).rootView; + ((ViewPager)container).addView(v, 0); + return v; + } + + @Override + public void destroyItem(ViewGroup container, int position, Object view) { + ((ViewPager)container).removeView((View)view); + } + + @Override + public boolean isViewFromObject(View view, Object key) { + return key == view; + } + } + + /** + * A class, that can be used as a TouchListener on any view (e.g. a Button). + * It cyclically runs a clickListener, emulating keyboard-like behaviour. First + * click is fired immediately, next before initialInterval, and subsequent before + * normalInterval. + *

+ *

Interval is scheduled before the onClick completes, so it has to run fast. + * If it runs slow, it does not generate skipped onClicks. + */ + public static class RepeatListener implements View.OnTouchListener { + + private Handler handler = new Handler(); + + private int initialInterval; + private final int normalInterval; + private final View.OnClickListener clickListener; + + private Runnable handlerRunnable = new Runnable() { + @Override + public void run() { + if (downView == null) { + return; + } + handler.removeCallbacksAndMessages(downView); + handler.postAtTime(this, downView, SystemClock.uptimeMillis() + normalInterval); + clickListener.onClick(downView); + } + }; + + private View downView; + + /** + * @param initialInterval The interval before first click event + * @param normalInterval The interval before second and subsequent click + * events + * @param clickListener The OnClickListener, that will be called + * periodically + */ + public RepeatListener(int initialInterval, int normalInterval, View.OnClickListener clickListener) { + if (clickListener == null) + throw new IllegalArgumentException("null runnable"); + if (initialInterval < 0 || normalInterval < 0) + throw new IllegalArgumentException("negative interval"); + + this.initialInterval = initialInterval; + this.normalInterval = normalInterval; + this.clickListener = clickListener; + } + + public boolean onTouch(View view, MotionEvent motionEvent) { + switch (motionEvent.getAction()) { + case MotionEvent.ACTION_DOWN: + downView = view; + handler.removeCallbacks(handlerRunnable); + handler.postAtTime(handlerRunnable, downView, SystemClock.uptimeMillis() + initialInterval); + clickListener.onClick(view); + return true; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_OUTSIDE: + handler.removeCallbacksAndMessages(downView); + downView = null; + return true; + } + return false; + } + } + + public interface OnEmojiconBackspaceClickedListener { + void onEmojiconBackspaceClicked(View v); + } + + public interface OnSoftKeyboardOpenCloseListener{ + void onKeyboardOpen(int keyBoardHeight); + void onKeyboardClose(); + } +} -- cgit v1.2.3