聊天APP界面中的表情
介绍:
聊天APP界面中的表情,自定义EmojiconTextView,和EmojiconEditText和一个表情EmojiconsFragment实现。
项目来源:http://www.itlanbao.com/code/20151211/10000/100689.html,喜欢的朋友可以下载完整源码参考参考。
效果截图:
其中表情页面用ViewPager实现多个页面的,其中自定义EmojisPagerAdapter并且提供两个方法:
@Override
public void onEmojiconClicked(Emojicon emojicon) {
EmojiconsFragment.input(editEmojicon, emojicon);
}
@Override
public void onEmojiconBackspaceClicked(View v) {
EmojiconsFragment.backspace(editEmojicon);
}
一个输入内容的,一个返回软键盘。自定义EmojiconGridFragment实现gridview效果。
使用的时候很方便直接引入库就可以了。
主要代码如下:
public class MainActivity extends FragmentActivity implements
EmojiconGridFragment.OnEmojiconClickedListener,
EmojiconsFragment.OnEmojiconBackspaceClickedListener {
EditText editEmojicon;
TextView txtEmojicon;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editEmojicon = (EditText) findViewById(R.id.editEmojicon);
txtEmojicon = (TextView) findViewById(R.id.txtEmojicon);
editEmojicon.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
txtEmojicon.setText(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
public void onEmojiconClicked(Emojicon emojicon) {
EmojiconsFragment.input(editEmojicon, emojicon);
}
@Override
public void onEmojiconBackspaceClicked(View v) {
EmojiconsFragment.backspace(editEmojicon);
}
}
其中EmojiconsFragment 类实现标签页面,部分代码如下:
package com.rockerhieu.emojicon;
import android.app.Activity;
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.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 {
private OnEmojiconBackspaceClickedListener mOnEmojiconBackspaceClickedListener;
private int mEmojiTabLastSelectedIndex = -1;
private View[] mEmojiTabs;
@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);
EmojisPagerAdapter emojisAdapter = new EmojisPagerAdapter(getFragmentManager(), Arrays.asList(
EmojiconGridFragment.newInstance(People.DATA),
EmojiconGridFragment.newInstance(Nature.DATA),
EmojiconGridFragment.newInstance(Objects.DATA),
EmojiconGridFragment.newInstance(Places.DATA),
EmojiconGridFragment.newInstance(Symbols.DATA)
));
emojisPager.setAdapter(emojisAdapter);
mEmojiTabs = new View[5];
mEmojiTabs[0] = view.findViewById(R.id.emojis_tab_0_people);
mEmojiTabs[1] = view.findViewById(R.id.emojis_tab_1_nature);
mEmojiTabs[2] = view.findViewById(R.id.emojis_tab_2_objects);
mEmojiTabs[3] = view.findViewById(R.id.emojis_tab_3_cars);
mEmojiTabs[4] = view.findViewById(R.id.emojis_tab_4_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);
}
}
}));
onPageSelected(0);
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());
}
}
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:
if (mEmojiTabLastSelectedIndex >= 0 && mEmojiTabLastSelectedIndex < mEmojiTabs.length) {
mEmojiTabs[mEmojiTabLastSelectedIndex].setSelected(false);
}
mEmojiTabs[i].setSelected(true);
mEmojiTabLastSelectedIndex = 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);
}
}