android 仿QQ表情,长按查看动图,移动手指可切换图片

以前在网上查,好像还没有这方面的资料,咬咬牙,自己搞一个吧。。

和QQ查看表情的操作方式一样,长按某一表情查看动画,拖动手指可以切换图片。实例如下:

说一下思想吧:

1、gif图用gifview显示;

2、当GridView检测到OnItemLongClick事件时,GridView被锁定不能滚动,用一个list存储当前可见的所有表情和它们的位置,同时将当前表情显示在gifview中;

3、当手指拖动到其他表情上时,检测GridView的OnTouch事件,将触摸点的位置与步骤2中存储的list中所有可见表情的位置作比较,如果是正在播放的表情则返回,否则更新gifview的显示内容及位置;

4、松开手指,设置gifview不可见。


为了方便使用,我把它封装成了一个类,主要的工作都在onTouch和onItemLongClick两个函数中,其他都是辅助函数。

package com.sollian.facegridview;

import java.util.ArrayList;
import java.util.HashMap;

import org.roisoleil.gifview.GifView;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.view.View.OnTouchListener;

/**
 * 仿QQ长按表情查看动图,移动手指可切换图片。
 * 
 * @author sollian
 * 
 */
public class FaceGridView extends FrameLayout implements OnTouchListener,
		OnItemLongClickListener {
	private Context context;
	/**
	 * 参数
	 */
	// 动态图的topmargin,以dp为单位
	private int nDynamicMarginTop = 0;
	// 震动时长,以ms为单位
	private int nVibrateTime = 300;
	/**
	 * 动态表情相关
	 */
	// FaceGridView在屏幕中的位置,对应x,y值
	private int gvLocation[] = new int[2];
	private ArrayList<HashMap<String, String>> listDynamicFace = new ArrayList<HashMap<String, String>>();
	/**
	 * 控件
	 */
	private GridView gridview;
	private LinearLayout ll;
	private GifView gifview;

	public FaceGridView(Context context) {
		this(context, null);
	}

	public FaceGridView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public FaceGridView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;
		LayoutInflater layoutInflater = LayoutInflater.from(getContext());
		View view = layoutInflater.inflate(R.layout.face_gridview, this, false);
		gridview = (GridView) view.findViewById(R.id.gridview);
		ll = (LinearLayout) view.findViewById(R.id.ll);
		gifview = (GifView) view.findViewById(R.id.gifview);
		FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		addView(view, params);

		gridview.setOnItemLongClickListener(this);
		gridview.setOnTouchListener(this);
	}

	/**
	 * 设置动态图的topmargin,以dp为单位
	 * 
	 * @param margin
	 */
	// public void setDynamicMarginTop(int margin) {
	// this.nDynamicMarginTop = margin;
	// }

	/**
	 * 设置动态图的背景
	 * 
	 * @param resId
	 */
	public void setDynamicBackground(int resid) {
		ll.setBackgroundResource(resid);
	}

	/**
	 * 设置动态图的背景
	 * 
	 * @param background
	 */
	@SuppressWarnings("deprecation")
	public void setDynamicBackground(Drawable background) {
		ll.setBackgroundDrawable(background);
	}

	/**
	 * 设置动态图的背景色
	 * 
	 * @param color
	 */
	public void setDynamicBackgroundColor(int color) {
		ll.setBackgroundColor(color);
	}

	/**
	 * 设置gridview的背景
	 * 
	 * @param resid
	 */
	public void setBackground(int resid) {
		gridview.setBackgroundResource(resid);
	}

	/**
	 * 设置gridview的背景
	 * 
	 * @param background
	 */
	@SuppressWarnings("deprecation")
	public void setBackgroundDrawable(Drawable background) {
		gridview.setBackgroundDrawable(background);
	}

	/**
	 * 设置gridview的背景
	 * 
	 * @param color
	 */
	public void setBackgroundColor(int color) {
		gridview.setBackgroundColor(color);
	}

	/**
	 * 设置震动时长,以ms为单位
	 * 
	 * @param time
	 */
	public void setVibrateTime(int time) {
		this.nVibrateTime = time;
	}

	/**
	 * 设置gridview的列数
	 * 
	 * @param numColumns
	 */
	public void setGridViewNumColumns(int numColumns) {
		gridview.setNumColumns(numColumns);
	}

	/**
	 * 设置gridview的adapter
	 * 
	 * @param adapter
	 */
	public void setAdapter(ListAdapter adapter) {
		gridview.setAdapter(adapter);
	}

	public void setOnItemClickListener(OnItemClickListener listener) {
		gridview.setOnItemClickListener(listener);
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE:
			// 获取触摸点相对于屏幕的坐标
			float eventX = gvLocation[0] + event.getX();
			float eventY = gvLocation[1] + event.getY();

			int x = 0;
			int y = 0;
			for (int i = 0; i < listDynamicFace.size(); i++) {
				HashMap<String, String> map = listDynamicFace.get(i);
				x = Integer.parseInt(map.get("x"));
				y = Integer.parseInt(map.get("y"));
				if (eventX >= x && eventX <= x + Util.dip2px(context, 40)
						&& eventY >= y
						&& eventY <= y + Util.dip2px(context, 40)) {
					if (i == gifview.getId()) {
						// 如果是正在播放的gif则返回
						return false;
					}
					// 更新显示的gif
					String imgName = map.get("imgName").toString();
					int resId = getResources().getIdentifier(imgName,// 需要转换的资源名称
							"drawable", // 资源类型
							context.getPackageName());// R类所在的包名
					gifview.setMovieResource(resId);
					gifview.setId(i);
					// 更新ll的位置
					LayoutParams params = new LayoutParams(Util.dip2px(context,
							70), Util.dip2px(context, 70));
					params.topMargin = y - gvLocation[1]
							+ Util.dip2px(context, nDynamicMarginTop);
					params.leftMargin = x - Util.dip2px(context, 20);
					if (params.topMargin < 0) {
						params.topMargin = 0;
					}
					if (params.leftMargin < 0) {
						params.leftMargin = 0;
					}
					if (params.leftMargin > gridview.getWidth()
							- Util.dip2px(context, 70)) {
						params.leftMargin = gridview.getWidth()
								- Util.dip2px(context, 70);
					}
					ll.setLayoutParams(params);
					break;
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			ll.setVisibility(View.GONE);
			break;
		}
		return false;
	}

	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view,
			int position, long id) {
		// 震动
		Util.vibrate(context, nVibrateTime);
		// 获取屏幕坐标
		gridview.getLocationInWindow(gvLocation);
		// 清空列表
		listDynamicFace.clear();
		/**
		 * 获取可见的表情列表
		 */
		int start = parent.getFirstVisiblePosition();
		int end = parent.getLastVisiblePosition();
		for (int i = 0; i <= end - start; i++) {
			HashMap<String, String> map = new HashMap<String, String>();
			View v = parent.getChildAt(i);
			int location[] = new int[2];
			if (null == v) {
				continue;
			}
			// 获取该表情在窗口中的坐标
			v.getLocationInWindow(location);
			if (v == view) {
				gifview.setId(i);
			}
			map.put("x", location[0] + "");
			map.put("y", location[1] + "");
			map.put("imgName", parent.getItemAtPosition(i + start).toString());
			listDynamicFace.add(map);
		}

		// 获取图片名称
		String imgName = parent.getItemAtPosition(position).toString();
		int resId = getResources().getIdentifier(imgName,// 需要转换的资源名称
				"drawable", // 资源类型
				context.getPackageName());// R类所在的包名
		gifview.setMovieResource(resId);
		// 获取控件在窗口中的绝对位置,不包括最顶部的状态栏
		int location[] = new int[2];
		view.getLocationInWindow(location);
		LayoutParams params = new LayoutParams(Util.dip2px(context, 70),
				Util.dip2px(context, 70));
		params.topMargin = location[1] - gvLocation[1]
				+ Util.dip2px(context, nDynamicMarginTop);
		params.leftMargin = location[0] - Util.dip2px(context, 20);
		if (params.topMargin < 0) {
			params.topMargin = 0;
		}
		if (params.leftMargin < 0) {
			params.leftMargin = 0;
		}
		if (params.leftMargin > gridview.getWidth() - Util.dip2px(context, 70)) {
			params.leftMargin = gridview.getWidth() - Util.dip2px(context, 70);
		}
		ll.setLayoutParams(params);
		ll.setVisibility(View.VISIBLE);
		// 返回true可禁止gridview滚动
		return true;
	}
}

最后附上项目地址吧,想参考的朋友可以下载看看:

FaceGridView

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值