package com.partynetwork.iparty.imessage; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.Scroller; import android.widget.TextView; import com.baidu.mobstat.StatService; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.AnimatorListenerAdapter; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.view.ViewHelper; import com.partynetwork.dataprovider.util.MediaFile; import com.partynetwork.dataprovider.util.OpenfireUtil; import com.partynetwork.dataprovider.util.TimeUtil; import com.partynetwork.iparty.R; import com.partynetwork.iparty.app.AppContext; import com.partynetwork.iparty.app.AppException; import com.partynetwork.iparty.app.bean.NoticeList; import com.partynetwork.iparty.app.common.BitmapManager; import com.partynetwork.iparty.app.common.UIHelper; import com.partynetwork.iparty.app.entities.ChartHisBean; import com.partynetwork.iparty.app.entities.CommonUser; import com.partynetwork.iparty.app.entities.IMessage; import com.partynetwork.iparty.app.manager.MessageManager; import com.partynetwork.iparty.app.manager.NoticeManager; import com.partynetwork.iparty.app.manager.UserManager; import com.partynetwork.iparty.app.util.StringUtils; import com.partynetwork.iparty.app.widget.SlideView; import com.partynetwork.iparty.info.MessageTypeInfo; import com.partynetwork.iparty.info.UserInfo; public class ImessagePage extends LinearLayout implements OnClickListener, OnItemClickListener, OnTouchListener, Callback { private Context mContext; private ListView mListView; private SlideAdapter slideAdapter; // 历史聊天记录 private List<ChartHisBean> inviteNotices = new ArrayList<ChartHisBean>(); // 上次处于打开状态的SlideView private SlideView mPointView; private SlideView mLastView; // 弹性滑动对象,提供弹性滑动效果 private Scroller mPointScroller; // 内置容器的宽度 单位:dp private int mHolderWidth = 120; // 分别记录上次滑动的坐标 private int mLastX = 0; private int mLastY = 0; // 用来控制滑动角度,仅当角度a满足如下条件才进行滑动:tan a = deltaX / deltaY > 2 private static final int TAN = 2; // 当前状态 private int state = 2; // SlideView的三种状态:开始滑动,打开,关闭 public static final int SLIDE_STATUS_OFF = 0; public static final int SLIDE_STATUS_START_SCROLL = 1; public static final int SLIDE_STATUS_ON = 2; private BitmapManager bitmapManager; private AppContext appContext; private Handler mHandler; public ImessagePage(Context context) { super(context); mContext=context; initView(); } /** * 实例化控件 */ private void initView() { // mContext = getContext(); appContext = (AppContext) mContext.getApplicationContext(); bitmapManager = new BitmapManager(); View.inflate(mContext, R.layout.imessage, this); mListView = (ListView) findViewById(R.id.imessage_list); TextView emptyView = new TextView(mContext); emptyView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); emptyView.setGravity(Gravity.CENTER); emptyView.setText("暂无消息……"); emptyView.setVisibility(View.GONE); ((ViewGroup) mListView.getParent()).addView(emptyView); mListView.setEmptyView(emptyView); slideAdapter = new SlideAdapter(mContext, inviteNotices); mListView.setAdapter(slideAdapter); mListView.setOnItemClickListener(this); mListView.setOnTouchListener(this); mHandler = new Handler(this); } /** * 获得通知 */ public void getNotices() { new Thread() { @Override public void run() { mHandler.sendEmptyMessage(0); Message msg = new Message(); try { NoticeList infos = appContext.getNoticeList(); msg.what = 1;// 成功 msg.obj = infos; } catch (AppException e) { e.printStackTrace(); msg.what = -1; msg.obj = e; } mHandler.sendMessage(msg); } }.start(); } /** * 获得用户信息 * * @param userId */ private void getUserInfo(final int userId) { new Thread() { public void run() { Message msg = new Message(); try { UserInfo info = appContext.getUserInfo(userId); CommonUser user = new CommonUser(); user.setUserAge(info.getUserAge()); user.setUserHeadUrl(info.getUserHeadUrl()); user.setUserId(info.getUserId()); user.setUserName(info.getUserName()); user.setUserSex(info.getUserSex()); user.setUserState(info.getUserState()); msg.what = 2;// 成功 msg.obj = user; } catch (AppException e) { e.printStackTrace(); msg.what = -1; msg.obj = e; } mHandler.sendMessage(msg); } }.start(); } @Override public boolean handleMessage(Message arg0) { switch (arg0.what) { case 0: // 刷新 System.out.println("arg0.what=========0"); inviteNotices.removeAll(inviteNotices); inviteNotices.addAll(NoticeManager.getInstance(mContext) .getRecentContactsWithLastMsg()); inviteNotices.addAll(MessageManager.getInstance(mContext) .getRecentContactsWithLastMsg()); System.out.println("我的标记inviteNotices==="+inviteNotices.size()); slideAdapter.notifyDataSetChanged(); break; case 1: System.out.println("arg0.what=========1"); NoticeList list = (NoticeList) arg0.obj; if (list == null) { return false; } // 对通知进行操作 // ...... List<MessageTypeInfo> typeLists = list.getNoticeList(); System.out.println("NoticeList.size=="+typeLists.size()); List<ChartHisBean> hisList = new ArrayList<ChartHisBean>(); for (MessageTypeInfo info : typeLists) { boolean has = false; // System.out.println("(info.getMessageNumber()=="+info.getMessageNumber()); if (info.getMessageNumber() > 0) { for (ChartHisBean ch : inviteNotices) { if (ch.getFrom() != null && ch.getFrom().equals( info.getMessageType() + "")) { has = true; ch.setNoticeSum(info.getMessageNumber()); } } } //这段代码移动位置 if (!has) { ChartHisBean hisBean = new ChartHisBean(); hisBean.setNoticeType(ChartHisBean.SYS_MSG); hisBean.setContent(info.getMessageStr()); hisBean.setTitle(info.getMessageStr()); hisBean.setFrom(info.getMessageType() + ""); hisBean.setNoticeSum(info.getMessageNumber()); hisList.add(hisBean); } } hisList.addAll(inviteNotices); inviteNotices.removeAll(inviteNotices); inviteNotices.addAll(hisList); slideAdapter.notifyDataSetChanged(); System.out.println("我的标记inviteNotices==="+inviteNotices.size()); System.out.println("我的标记hisList==="+hisList.size()); break; case 2: // 成功获取用户信息 System.out.println("arg0.what=========2 "); CommonUser user = (CommonUser) arg0.obj; if (user == null) { return false; } UserManager.getInstance(mContext).saveOrUpdateUser(user); slideAdapter.notifyDataSetChanged(); break; case -1: System.out.println("arg0.what=========-1 "); AppException e = (AppException) arg0.obj; if (AppContext.getInstance().isLogin()) { e.makeToast(mContext); } break; default: break; } return false; } /** * 页面恢复方法 */ public void onResume() { getNotices(); StatService.onPageStart(mContext, "imessagePage"); } public void onPause() { StatService.onPageEnd(mContext, "imessagePage"); } public void msgReceive(IMessage msg) { boolean has = false; for (ChartHisBean ch : inviteNotices) { if (ch.getFrom() != null && ch.getFrom().equals(msg.getWithUser())) { has = true; ch.setContent(msg.getContent()); ch.setNoticeTime(msg.getTime()); ch.setNoticeSum(ch.getNoticeSum() + 1); } } if (inviteNotices.size() == 0) { getNotices(); } if (!has) { ChartHisBean bean = new ChartHisBean(); bean.setContent(msg.getContent()); bean.setFrom(msg.getWithUser()); bean.setNoticeSum(1); bean.setNoticeTime(msg.getTime()); bean.setNoticeType(ChartHisBean.CHAT_MSG); inviteNotices.add(bean); } slideAdapter.notifyDataSetChanged(); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (state == SLIDE_STATUS_OFF) { if (inviteNotices.get(position).getNoticeType() == ChartHisBean.SYS_MSG) { UIHelper.showNotice(mContext, StringUtils.toInt(inviteNotices .get(position).getFrom(), 0)); } else { System.out.println("getFrom()========="+inviteNotices.get(position).getFrom()); UIHelper.showChat(mContext, inviteNotices.get(position) .getFrom()); } } } @Override public void onClick(View v) { // 这里处理删除按钮的点击事件,可以删除对话 if (v.getId() == R.id.holder) { final int position = mListView.getPositionForView(v); if (position != ListView.INVALID_POSITION) { // 在此方法中执行item删除之后,其他的item向上或者向下滚动的动画 final View dismissView = mListView.getChildAt(position); final ViewGroup.LayoutParams lp = dismissView.getLayoutParams();// 获取item的布局参数 final int originalHeight = dismissView.getHeight();// item的高度 ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 0) .setDuration(150); animator.start(); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { MessageManager.getInstance(mContext).delChatHisWithSb( inviteNotices.get(position).getFrom()); NoticeManager.getInstance(mContext).delNoticeByType( StringUtils.toInt(inviteNotices.get(position) .getFrom(), 0)); inviteNotices.remove(position); slideAdapter.notifyDataSetChanged(); // 这段代码很重要,因为我们并没有将item从ListView中移除,而是将item的高度设置为0 // 所以我们在动画执行完毕之后将item设置回来 ViewHelper.setAlpha(dismissView, 1f); ViewHelper.setTranslationX(dismissView, 0); ViewGroup.LayoutParams lp = dismissView .getLayoutParams(); lp.height = originalHeight; dismissView.setLayoutParams(lp); } }); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { // 这段代码的效果是ListView删除某item之后,其他的item向上滑动的效果 lp.height = (Integer) valueAnimator.getAnimatedValue(); dismissView.setLayoutParams(lp); } }); } } } private class SlideAdapter extends ArrayAdapter<ChartHisBean> { SlideAdapter(Context context, List<ChartHisBean> objects) { super(context, 0, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { ChartHisBean notice = (ChartHisBean) getItem(position); ViewHolder holder; SlideView slideView = (SlideView) convertView; if (slideView == null) { View itemView = null; itemView = LayoutInflater.from(mContext).inflate( R.layout.message_item_chat, null); slideView = new SlideView(mContext); // 这里把item加入到slideView slideView.setContentView(itemView); // 下面是做一些数据缓存 holder = new ViewHolder(slideView); slideView.setTag(holder); // convertView.setTag(holder); } else { holder = (ViewHolder) slideView.getTag(); } notice.setSlideView(slideView); setDate(holder, notice); return slideView; } } /** * 处理数据 * * @param notice */ private void setDate(ViewHolder holder, ChartHisBean notice) { Integer ppCount = notice.getNoticeSum(); if (notice.getNoticeType() == ChartHisBean.SYS_MSG) { holder.newTitle.setText(notice.getTitle()); holder.newTitle.setVisibility(View.GONE); holder.newDate.setVisibility(View.GONE); int from = StringUtils.toInt(notice.getFrom(), 0); // 0:系统消息 // 1:iParty提醒 // 2:打招呼 // 3:新的i好友 // 4:提到我的 // 5:投票 // 6:评论 // 7:赞 int res = 0; String content = ""; switch (from) { case 0: res = R.drawable.message_sys_notice_icon; content = "系统消息"; break; case 1: res = R.drawable.message_sys_party_icon; content = "iParty提醒"; break; case 2: res = R.drawable.message_sys_hi_icon; content = "打招呼"; break; case 3: res = R.drawable.message_sys_friend_icon; content = "新的i好友"; break; case 4: res = R.drawable.message_sys_at_icon; content = "提到我的"; break; case 5: res = R.drawable.message_sys_vote_icon; content = "投票"; break; case 6: res = R.drawable.message_sys_discuss_icon; content = "评论"; break; case 7: res = R.drawable.message_sys_praise_icon; content = "赞"; break; default: res = R.drawable.message_sys_notice_icon; content = "系统消息"; break; } holder.itemIcon.setImageResource(res); holder.newContent.setText(content); } else { holder.newTitle.setVisibility(View.VISIBLE); holder.newDate.setVisibility(View.VISIBLE); String userId = OpenfireUtil.getUserNameByJid(notice.getFrom()); CommonUser user = null; user = UserManager.getInstance(mContext).getUserbyId(userId); if (user != null) { bitmapManager .loadBitmap(user.getUserHeadUrl(), holder.itemIcon); holder.newTitle.setText(user.getUserName()); } else { getUserInfo(Integer.parseInt(userId)); } if (MediaFile.isAudioFileType(notice.getContent())) { holder.newContent.setText("[语音]"); } else if (MediaFile.isImageFileType(notice.getContent())) { holder.newContent.setText("[图片]"); } else { holder.newContent.setText(notice.getContent()); } } holder.newDate.setText(TimeUtil.friendly_time(notice.getNoticeTime())); holder.deleteHolder.setOnClickListener(this); if (ppCount != null && ppCount > 0) { holder.paopao.setText(ppCount + ""); holder.paopao.setVisibility(View.VISIBLE); holder.newDate.setVisibility(View.GONE); } else { holder.paopao.setVisibility(View.GONE); if (notice.getNoticeType() == ChartHisBean.CHAT_MSG) { holder.newDate.setVisibility(View.VISIBLE); } } } private static class ViewHolder { public ImageView itemIcon; public TextView newTitle; public TextView newContent; public TextView newDate; public TextView paopao; public ViewGroup deleteHolder; ViewHolder(View view) { itemIcon = (ImageView) view.findViewById(R.id.icon); newTitle = (TextView) view.findViewById(R.id.title); newContent = (TextView) view.findViewById(R.id.content); newDate = (TextView) view.findViewById(R.id.time); paopao = (TextView) view.findViewById(R.id.number); deleteHolder = (ViewGroup) view.findViewById(R.id.holder); } } @Override public boolean onTouch(View v, MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); int scrollX = 0; if (mPointView != null) { scrollX = mPointView.getScrollX(); } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { if (mPointScroller != null && !mPointScroller.isFinished()) { mPointScroller.abortAnimation(); } int position = mListView.pointToPosition(x, y); mPointView = (SlideView) mListView.getChildAt(position); if (mPointView != null) { mPointScroller = new Scroller(mPointView.getContext()); // 初始化弹性滑动对象 state = SLIDE_STATUS_START_SCROLL; onSlide(mPointView, state); } break; } case MotionEvent.ACTION_MOVE: { int deltaX = x - mLastX; int deltaY = y - mLastY; if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) { // 滑动不满足条件,不做横向滑动 break; } // 计算滑动终点是否合法,防止滑动越界 int newScrollX = scrollX - deltaX; if (deltaX != 0) { if (newScrollX < 0) { newScrollX = 0; } else if (newScrollX > mHolderWidth) { newScrollX = mHolderWidth; } if (mPointView != null) { mPointView.scrollTo(newScrollX, 0); } } break; } case MotionEvent.ACTION_UP: { int newScrollX = 0; // 这里做了下判断,当松开手的时候,会自动向两边滑动,具体向哪边滑,要看当前所处的位置 if (scrollX - mHolderWidth * 0.75 > 0) { newScrollX = mHolderWidth; } // 慢慢滑向终点 smoothScrollTo(mPointView, mPointScroller, newScrollX, 0); // 通知上层滑动事件 state = scrollX < 10 ? SLIDE_STATUS_OFF : SLIDE_STATUS_ON; onSlide(mPointView, state); break; } default: break; } mLastX = x; mLastY = y; return super.onTouchEvent(event); } private void smoothScrollTo(SlideView slideView, Scroller scroller, int destX, int destY) { // 缓慢滚动到指定位置 int scrollX = 0; if (slideView != null) { scrollX = slideView.getScrollX(); } int delta = destX - scrollX; // 以三倍时长滑向destX,效果就是慢慢滑动 if (scroller != null) { scroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3); } invalidate(); } public void computeScroll() { if (mPointView != null && mPointScroller != null && mPointScroller.computeScrollOffset()) { mPointView.scrollTo(mPointScroller.getCurrX(), mPointScroller.getCurrY()); postInvalidate(); } } public void onSlide(View view, int status) { // 如果当前存在已经打开的SlideView,那么将其关闭 if (mLastView != null && mLastView != view) { // shrink(); mLastView.scrollTo(0, 0); } // 记录本次处于打开状态的view if (status == SLIDE_STATUS_ON) { mLastView = (SlideView) view; } } }