这几天在研究QQ表情,闲来无事,从网上下载资源,感觉代码量太大,看的云里雾里,后来果断自己写了一个Demo,虽然功能不全,但是自己体会很深,废话不多说,一步步来把
先看下整体的效果图吧
代码下载地址 http://download.csdn.net/detail/u013210620/8815585
首先看整体界面的布局效果+布局文件吧
布局文件
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="fill_parent" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" > <ListView android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="50dp" android:background="#EEE9E9" android:gravity="center" android:orientation="horizontal" > <ImageView android:id="@+id/iv_show" android:layout_width="30dp" android:layout_height="30dp" android:layout_marginLeft="5dp" android:background="@drawable/selector_show_biaoqing" /> <EditText android:id="@+id/tv_biaoqingkuang" android:layout_width="0dp" android:layout_height="30dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_weight="1" android:background="@drawable/textview_style" android:gravity="center_vertical" android:hint="选择表情" android:inputType="textMultiLine" /> <TextView android:id="@+id/tv_send" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="5dp" android:text="发送" android:textSize="20dp" /> </LinearLayout> <LinearLayout android:id="@+id/ll_biaoqing" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:visibility="visible" > <android.support.v4.view.ViewPager android:id="@+id/biaoqing_viewpager" android:layout_width="fill_parent" android:layout_height="150dp" android:background="#FFDFD7D7" android:visibility="visible" /> </LinearLayout> <RelativeLayout android:id="@+id/rl_indicator" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#FFDFD7D7" android:gravity="center" > <ImageView android:id="@+id/iv_indicator1" android:layout_width="30dp" android:layout_height="30dp" android:background="@drawable/flag_online" /> <!-- <ImageView android:id="@+id/iv_indicator_up1" android:layout_width="30dp" android:layout_height="30dp" android:layout_centerVertical="true" android:background="@drawable/selector_dot" /> --> <ImageView android:id="@+id/iv_indicator2" android:layout_width="30dp" android:layout_height="30dp" android:layout_toRightOf="@id/iv_indicator1" android:background="@drawable/flag_offline" /> <!-- <ImageView android:visibility="gone" android:layout_toRightOf="@id/iv_indicator_up1" android:id="@+id/iv_indicator_up2" android:layout_width="30dp" android:layout_height="30dp" android:layout_centerVertical="true" android:background="@drawable/flag_online" /> --> </RelativeLayout> </LinearLayout>
接下来看主布局文件代码
MainActivity.java
package com.example.qqsmiledemo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.style.ImageSpan; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.example.qqsmiledemo.MyBiaoQingFragment1.OnArticleSelectedListener; import com.example.qqsmiledemo.MyBiaoQingFragment2.OnArticleSelectedListener2; public class MainActivity extends FragmentActivity implements OnClickListener, OnArticleSelectedListener, OnArticleSelectedListener2 { //切换是否显示表情栏的控件 private ImageView iv_show; //输入、发送表情框控件 private TextView tv_biaoqingkuang,tv_send; //表情框控件 private LinearLayout ll_biaoqing; //viewpager切换时,高亮显示控件 private RelativeLayout rl_indicator; private ImageView iv_indicator1; private ImageView iv_indicator2; //viewpager private ViewPager biaoqing_viewpager; //adapter private BiaoQingAdapter biaoQingAdapter; // 默认表情区域不显示(隐藏状态) private boolean isBiaoqingShow = false; //目前viewpager所在页面的position private int currPos; private SpannableStringBuilder spb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { iv_show = (ImageView) findViewById(R.id.iv_show); tv_biaoqingkuang = (TextView) findViewById(R.id.tv_biaoqingkuang); tv_send = (TextView) findViewById(R.id.tv_send); ll_biaoqing = (LinearLayout) findViewById(R.id.ll_biaoqing); iv_indicator1 = (ImageView) findViewById(R.id.iv_indicator1); iv_indicator2 = (ImageView) findViewById(R.id.iv_indicator2); rl_indicator = (RelativeLayout) findViewById(R.id.rl_indicator); biaoqing_viewpager = (ViewPager) findViewById(R.id.biaoqing_viewpager); biaoQingAdapter = new BiaoQingAdapter(getSupportFragmentManager()); biaoqing_viewpager.setAdapter(biaoQingAdapter); // 设置页面改变监听 biaoqing_viewpager.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { switch (position) { case 0: if (currPos == 1) { iv_indicator1 .setBackgroundResource(R.drawable.flag_online); iv_indicator2 .setBackgroundResource(R.drawable.flag_offline); } break; case 1: if (currPos == 0) { iv_indicator2 .setBackgroundResource(R.drawable.flag_online); iv_indicator1 .setBackgroundResource(R.drawable.flag_offline); } break; default: break; } currPos = position; } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); iv_show.setOnClickListener(this); tv_send.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.iv_show: if (!isBiaoqingShow) { ll_biaoqing.setVisibility(View.VISIBLE); rl_indicator.setVisibility(View.VISIBLE); isBiaoqingShow = true; } else { ll_biaoqing.setVisibility(View.GONE); rl_indicator.setVisibility(View.GONE); isBiaoqingShow = false; } break; case R.id.tv_send: Toast.makeText(MainActivity.this, "聊天界面功能未实现", 0).show(); break; default: break; } } //实现接口方法 @Override public void onArticleSelected(int pagePos, int[] imgs, int position) { if (pagePos == 0) { if (position < imgs.length - 1) { spb = new SpannableStringBuilder(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgs[position]); bitmap = Bitmap.createScaledBitmap(bitmap, 40, 40, true); // imageSpan用来让图片代替字体的 ImageSpan imageSpan = new ImageSpan(this, bitmap); // 用来设置EditText多种样式的类 SpannableString spanString = new SpannableString("表情"); // 指定位置替换字体 spanString.setSpan(imageSpan, 0, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spb.append(spanString); tv_biaoqingkuang.append(spb); } else { Toast.makeText(MainActivity.this, "回退删除表情未实现,用系统自带的吧", 0) .show(); } } else if (pagePos == 1) { if (position < imgs.length - 1) { spb = new SpannableStringBuilder(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imgs[position]); bitmap = Bitmap.createScaledBitmap(bitmap, 40, 40, true); ImageSpan imageSpan = new ImageSpan(this, bitmap); SpannableString spanString = new SpannableString("表情"); spanString.setSpan(imageSpan, 0, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spb.append(spanString); tv_biaoqingkuang.append(spb); } else { Toast.makeText(MainActivity.this, "回退删除表情未实现,用系统自带的吧", 0) .show(); } } } }
接下来看BiaoQingAdapter
package com.example.qqsmiledemo; import java.util.ArrayList; import java.util.List; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; public class BiaoQingAdapter extends FragmentPagerAdapter { private List<Fragment> Filmfragments = new ArrayList<>(); public BiaoQingAdapter(FragmentManager fm) { super(fm); Filmfragments.add(new MyBiaoQingFragment1()); Filmfragments.add(new MyBiaoQingFragment2()); } @Override public Fragment getItem(int pos) { return Filmfragments.get(pos); } @Override public int getCount() { return Filmfragments.size(); } }
接下来看2个Fragment
MyBiaoQingFragment1
package com.example.qqsmiledemo; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; public class MyBiaoQingFragment1 extends Fragment { private View biaoqing1View; private GridView gv_biaoqing1; private BiaoQingFragment1Adapter biaoQingFragment1Adapter; private OnArticleSelectedListener mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { biaoqing1View = View.inflate(getActivity(), R.layout.biaoqing1, null); initView(); return biaoqing1View; } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { //强转换 mListener = (OnArticleSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + "must implement OnArticleSelectedListener"); } } private void initView() { gv_biaoqing1 = (GridView) biaoqing1View.findViewById(R.id.gv_biaoqing1); biaoQingFragment1Adapter = new BiaoQingFragment1Adapter(getActivity()); gv_biaoqing1.setAdapter(biaoQingFragment1Adapter); gv_biaoqing1.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 每个条目的点击监听事件 mListener.onArticleSelected(0,imgs, position); } }); } private int[] imgs = { R.drawable.emoji_0, R.drawable.emoji_1, R.drawable.emoji_2, R.drawable.emoji_3, R.drawable.emoji_4, R.drawable.emoji_5, R.drawable.emoji_6, R.drawable.emoji_7, R.drawable.emoji_8, R.drawable.emoji_9, R.drawable.emoji_10, R.drawable.emoji_11, R.drawable.emoji_12, R.drawable.emoji_13, R.drawable.emoji_14, R.drawable.emoji_15, R.drawable.emoji_16, R.drawable.emoji_17, R.drawable.emoji_18, R.drawable.emoji_19, R.drawable.top_return_n, }; class BiaoQingFragment1Adapter extends BaseAdapter { private Context context; BiaoQingFragment1Adapter(Context context) { this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return imgs.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return imgs[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = View.inflate(context, R.layout.picture_item, null); ImageView imageView = (ImageView) view.findViewById(R.id.image); imageView.setBackgroundResource(imgs[position]); return view; } } /** * 回调接口--每个表情被选中调用接口 * */ public interface OnArticleSelectedListener { public void onArticleSelected(int pagePos,int[] imgs, int position); } }
MyBiaoQingFragment2
package com.example.qqsmiledemo; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; public class MyBiaoQingFragment2 extends Fragment { private View biaoqing2View; private GridView gv_biaoqing2; private BiaoQingFragment2Adapter biaoQingFragment2Adapter; private OnArticleSelectedListener2 mListener; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { biaoqing2View = View.inflate(getActivity(), R.layout.biaoqing2, null); initView(); return biaoqing2View; } private void initView() { gv_biaoqing2 = (GridView) biaoqing2View.findViewById(R.id.gv_biaoqing2); biaoQingFragment2Adapter = new BiaoQingFragment2Adapter(getActivity()); gv_biaoqing2.setAdapter(biaoQingFragment2Adapter); gv_biaoqing2.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mListener.onArticleSelected(1,imgs, position); } }); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnArticleSelectedListener2) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + "must implement OnArticleSelectedListener"); } } private int[] imgs = { R.drawable.emoji_20, R.drawable.emoji_21, R.drawable.emoji_22, R.drawable.emoji_23, R.drawable.emoji_24, R.drawable.emoji_25, R.drawable.emoji_26, R.drawable.emoji_27, R.drawable.emoji_28, R.drawable.emoji_29, R.drawable.emoji_30, R.drawable.emoji_31, R.drawable.emoji_32, R.drawable.emoji_33, R.drawable.emoji_34, R.drawable.top_return_n, }; class BiaoQingFragment2Adapter extends BaseAdapter{ private Context context; BiaoQingFragment2Adapter(Context context){ this.context = context; } @Override public int getCount() { // TODO Auto-generated method stub return imgs.length; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return imgs[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = View.inflate(context, R.layout.picture_item, null); ImageView imageView = (ImageView) view.findViewById(R.id.image); imageView.setBackgroundResource(imgs[position]); return view; } } public interface OnArticleSelectedListener2 { public void onArticleSelected(int pagePos,int[] imgs, int position); } }
然后还有2个Fragment的布局文件
biaoqing1.xml
<?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:orientation="vertical" > <GridView android:padding="10dp" android:id="@+id/gv_biaoqing1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="35dp" android:gravity="center" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:horizontalSpacing="10dp" android:verticalSpacing="10dp" > </GridView> </LinearLayout>
biaoqing2.xml
<?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:orientation="vertical" > <GridView android:padding="10dp" android:id="@+id/gv_biaoqing2" android:layout_width="fill_parent" android:layout_height="fill_parent" android:columnWidth="35dp" android:gravity="center" android:numColumns="auto_fit" android:stretchMode="columnWidth" android:horizontalSpacing="10dp" android:verticalSpacing="10dp" > </GridView> </LinearLayout>
另外GridView里面的每个Item
picture_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/image" android:layout_width="30dp" android:layout_height="30dp" android:layout_gravity="center" android:padding="4dp" android:scaleType="fitXY" /> </LinearLayout>
另外还有那个输入表情的文本框的圆角布局文件
selector_show_biaoqing.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/ic_open_emoji_pressed"/> <item android:state_pressed="false" android:drawable="@drawable/ic_open_emoji_unpress"/> <item android:drawable="@drawable/ic_open_emoji_unpress"/> </selector>
textview_style.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#ffffff" /> <corners android:radius="5dp" /> <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" /> </shape>
时间: 2024-10-09 20:08:52