Java tutorial
/* * Copyright 2014 Hieu Rocker * * 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 com.rockerhieu.emojicon; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.*; import android.widget.EditText; import com.rockerhieu.emojicon.emoji.*; import java.util.Arrays; import java.util.List; /** * @author Hieu Rocker (rockerhieu@gmail.com). */ public class EmojiconsFragment extends Fragment implements ViewPager.OnPageChangeListener, EmojiconRecents { private OnEmojiconBackspaceClickedListener mOnEmojiconBackspaceClickedListener; private int mEmojiTabLastSelectedIndex = -1; private View[] mEmojiTabs; private PagerAdapter mEmojisAdapter; private EmojiconRecentsManager mRecentsManager; private boolean mUseSystemDefault = false; private static final String USE_SYSTEM_DEFAULT_KEY = "useSystemDefaults"; public static EmojiconsFragment newInstance(boolean useSystemDefault) { EmojiconsFragment fragment = new EmojiconsFragment(); Bundle bundle = new Bundle(); bundle.putBoolean(USE_SYSTEM_DEFAULT_KEY, useSystemDefault); fragment.setArguments(bundle); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.emojicons, container, false); final ViewPager emojisPager = (ViewPager) view.findViewById(R.id.emojis_pager); emojisPager.setOnPageChangeListener(this); // we handle recents EmojiconRecents recents = this; mEmojisAdapter = new EmojisPagerAdapter(getFragmentManager(), Arrays.asList(EmojiconRecentsGridFragment.newInstance(mUseSystemDefault), EmojiconGridFragment.newInstance(People.DATA, recents, mUseSystemDefault), EmojiconGridFragment.newInstance(Nature.DATA, recents, mUseSystemDefault), EmojiconGridFragment.newInstance(Objects.DATA, recents, mUseSystemDefault), EmojiconGridFragment.newInstance(Places.DATA, recents, mUseSystemDefault), EmojiconGridFragment.newInstance(Symbols.DATA, recents, mUseSystemDefault))); 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 View.OnClickListener() { @Override public void onClick(View v) { if (mOnEmojiconBackspaceClickedListener != null) { mOnEmojiconBackspaceClickedListener.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; } @Override public void onAttach(Activity activity) { super.onAttach(activity); if (getActivity() instanceof OnEmojiconBackspaceClickedListener) { mOnEmojiconBackspaceClickedListener = (OnEmojiconBackspaceClickedListener) getActivity(); } else if (getParentFragment() instanceof OnEmojiconBackspaceClickedListener) { mOnEmojiconBackspaceClickedListener = (OnEmojiconBackspaceClickedListener) getParentFragment(); } else { throw new IllegalArgumentException(activity + " must implement interface " + OnEmojiconBackspaceClickedListener.class.getSimpleName()); } } @Override public void onDetach() { mOnEmojiconBackspaceClickedListener = null; super.onDetach(); } 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) { final ViewPager emojisPager = (ViewPager) getView().findViewById(R.id.emojis_pager); EmojiconRecentsGridFragment fragment = (EmojiconRecentsGridFragment) mEmojisAdapter .instantiateItem(emojisPager, 0); 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 FragmentStatePagerAdapter { private List<EmojiconGridFragment> fragments; public EmojisPagerAdapter(FragmentManager fm, List<EmojiconGridFragment> fragments) { super(fm); this.fragments = fragments; } @Override public Fragment getItem(int i) { return fragments.get(i); } @Override public int getCount() { return fragments.size(); } } /** * 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. * <p/> * <p>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); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mUseSystemDefault = getArguments().getBoolean(USE_SYSTEM_DEFAULT_KEY); } else { mUseSystemDefault = false; } } }