/* * 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 my.home.lehome.adapter; import android.content.Context; import android.graphics.Bitmap; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer; import com.nostra13.universalimageloader.core.imageaware.ImageAware; import com.nostra13.universalimageloader.core.imageaware.ImageViewAware; import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; import com.skyfishjy.library.RippleBackground; import java.lang.ref.WeakReference; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import my.home.common.FourStateHandler; import my.home.lehome.R; import my.home.lehome.asynctask.LoadLongMsgAsyncTask; import my.home.lehome.helper.LocationHelper; import my.home.lehome.util.ChatItemUtils; import my.home.lehome.util.Constants; import my.home.model.entities.ChatItem; import my.home.model.entities.ChatItemConstants; import my.home.model.manager.DBStaticManager; public class ChatItemArrayAdapter extends ArrayAdapter<ChatItem> implements FourStateHandler.StateCallback { public static final String TAG = ChatItemArrayAdapter.class.getSimpleName(); private ResendButtonClickListener mResendButtonClickListener; private ImageClickListener mImageClickListener; private WeakReference<LongMsgListener> mLongMsgListener; private DisplayImageOptions options; private Map<Integer, ViewHolder> mViewHolders; private Set<Integer> mLoadingItems; @Override public void add(ChatItem object) { super.add(object); } public void setData(List<ChatItem> items) { clear(); setNotifyOnChange(false); if (items != null) { for (ChatItem item : items) add(item); } setNotifyOnChange(true); notifyDataSetChanged(); } public ChatItemArrayAdapter(Context context, int textViewResourceId) { super(context, textViewResourceId); options = new DisplayImageOptions.Builder() // .showImageOnLoading(R.drawable.ic_stub) // .showImageForEmptyUri(R.drawable.ic_empty) .resetViewBeforeLoading(true) .showImageOnFail(R.drawable.left_chatitem_disconnect) // .showImageOnLoading(R.drawable.left_chatitem_loading) .cacheInMemory(true) .cacheOnDisk(true) .considerExifParams(true) .displayer(new RoundedBitmapDisplayer(10)) .build(); mViewHolders = new HashMap<>(); mLoadingItems = new HashSet<>(); } @Override public int getViewTypeCount() { return 5; } @Override public int getItemViewType(int position) { return getItem(position).getType(); } public View getView(int position, View convertView, ViewGroup parent) { ChatItem chatItem = getItem(position); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); switch (chatItem.getType()) { case ChatItemConstants.TYPE_CLIENT: convertView = inflater.inflate(R.layout.chat_item_client, parent, false); break; case ChatItemConstants.TYPE_SERVER: convertView = inflater.inflate(R.layout.chat_item_server, parent, false); break; case ChatItemConstants.TYPE_SERVER_IMAGE: convertView = inflater.inflate(R.layout.chat_item_server_img, parent, false); break; case ChatItemConstants.TYPE_SERVER_LOC: convertView = inflater.inflate(R.layout.chat_item_server_loc, parent, false); break; case ChatItemConstants.TYPE_SERVER_LONG_MSG: convertView = inflater.inflate(R.layout.chat_item_server_msg, parent, false); break; } final ViewHolder viewHolder = new ViewHolder(); viewHolder.rippleBackground = (RippleBackground) convertView.findViewById(R.id.profile_rippleBackground); viewHolder.errorButton = (ImageButton) convertView.findViewById(R.id.resend_imagebutton); viewHolder.dateTextView = (TextView) convertView.findViewById(R.id.date_textview); viewHolder.chatTextView = (TextView) convertView.findViewById(R.id.chat_content_textview); viewHolder.imageView = (ImageView) convertView.findViewById(R.id.chat_content_imageview); viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.chat_pending_progressBar); // 先使textview捕获longpress事件 viewHolder.chatTextView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return false; } }); if (viewHolder.imageView != null) { viewHolder.imageView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { return false; } }); } convertView.setTag(viewHolder); } final ViewHolder viewHolder = (ViewHolder) convertView.getTag(); mViewHolders.put(position, viewHolder); if (chatItem.isClient()) { handleMeItem(position, chatItem, viewHolder); } else if (chatItem.isServerImageItem()) { handlerServerImageItem(chatItem, viewHolder); } else if (chatItem.isServer()) { handleServerItem(chatItem, viewHolder); } else if (chatItem.isServerLocItem()) { handlerServerLocItem(chatItem, viewHolder); } else if (chatItem.isServerLongMsgItem()) { handlerServerLongMsgItem(position, chatItem, viewHolder); } String dateString = getTimeWithFormat(position); if (dateString != null) { viewHolder.dateTextView.setText(dateString); viewHolder.dateTextView.setVisibility(View.VISIBLE); } else { viewHolder.dateTextView.setVisibility(View.INVISIBLE); } return convertView; } private void handlerServerLocItem(ChatItem chatItem, final ViewHolder viewHolder) { Context context = getContext(); String src = chatItem.getContent(); final String[] location = LocationHelper.parseLocationFromSrc(src); final String latitude = location[2]; final String longitude = location[3]; final String mapUrl = LocationHelper.getBaiduStaticMapImgUrl( longitude, latitude, viewHolder.imageView.getLayoutParams().width, viewHolder.imageView.getLayoutParams().height, 18); final String menuTitle = context.getString(R.string.loc_open_in_browser); String summary = context.getString(R.string.loc_current_addr, location[0], location[1]); viewHolder.chatTextView.setText(summary); viewHolder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mImageClickListener != null) { Bundle bundle = new Bundle(); bundle.putSerializable("type", ClickableImageType.LOCATION); bundle.putString("imageURL", mapUrl); bundle.putString("extraTitle", menuTitle); bundle.putParcelable("extraIntent", LocationHelper.getBaiduMapUrlIntent( longitude, latitude, location[0], location[1], "lehome", "lehome" )); bundle.putString("longitude", longitude); bundle.putString("latitude", latitude); mImageClickListener.onImageViewClicked(bundle); } } }); ImageAware imageAware = new ImageViewAware(viewHolder.imageView, false); ImageLoader.getInstance().displayImage(mapUrl, imageAware, options, new SimpleImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { viewHolder.progressBar.setProgress(0); viewHolder.progressBar.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { Log.w(TAG, failReason.toString()); viewHolder.progressBar.setVisibility(View.GONE); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { viewHolder.progressBar.setVisibility(View.GONE); } }, new ImageLoadingProgressListener() { @Override public void onProgressUpdate(String imageUri, View view, int current, int total) { viewHolder.progressBar.setProgress(Math.round(100.0f * current / total)); } } ); } private void handleMeItem(int position, ChatItem chatItem, ViewHolder viewHolder) { viewHolder.rippleBackground.startRippleAnimation(); if (chatItem.getState() == Constants.CHATITEM_STATE_SUCCESS || !chatItem.isClient()) { viewHolder.errorButton.setVisibility(View.GONE); viewHolder.rippleBackground.stopRippleAnimation(); } else if (chatItem.getState() == Constants.CHATITEM_STATE_PENDING) { viewHolder.errorButton.setVisibility(View.GONE); viewHolder.rippleBackground.startRippleAnimation(); } else { viewHolder.errorButton.setVisibility(View.VISIBLE); viewHolder.rippleBackground.stopRippleAnimation(); if (mResendButtonClickListener != null) { final int pos = position; viewHolder.errorButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mResendButtonClickListener.onResendButtonClicked(pos); } }); } } viewHolder.chatTextView.setText(chatItem.getContent()); } private void handleServerItem(ChatItem chatItem, ViewHolder viewHolder) { // viewHolder.imageView.setVisibility(View.GONE); viewHolder.chatTextView.setVisibility(View.VISIBLE); viewHolder.chatTextView.setText(chatItem.getContent()); } private void handlerServerImageItem(ChatItem chatItem, final ViewHolder viewHolder) { viewHolder.imageView.setVisibility(View.VISIBLE); viewHolder.chatTextView.setVisibility(View.GONE); final String image_url = chatItem.getContent(); viewHolder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mImageClickListener != null) { Bundle bundle = new Bundle(); bundle.putString("imageURL", image_url); bundle.putSerializable("type", ClickableImageType.IMAGE); mImageClickListener.onImageViewClicked(bundle); } } }); ImageAware imageAware = new ImageViewAware(viewHolder.imageView, false); ImageLoader.getInstance().displayImage(ChatItemUtils.getThumbnailPath(image_url), imageAware, options, new SimpleImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { viewHolder.progressBar.setProgress(0); viewHolder.progressBar.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { Log.w(TAG, failReason.toString()); viewHolder.progressBar.setVisibility(View.GONE); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { viewHolder.progressBar.setVisibility(View.GONE); } }, new ImageLoadingProgressListener() { @Override public void onProgressUpdate(String imageUri, View view, int current, int total) { viewHolder.progressBar.setProgress(Math.round(100.0f * current / total)); } } ); } private void handlerServerLongMsgItem(int position, ChatItem chatItem, ViewHolder viewHolder) { if (!mLoadingItems.contains(position)) { mLoadingItems.add(position); viewHolder.chatTextView.setText(""); Bundle bundle = new Bundle(); bundle.putInt("pos", position); FourStateHandler handler = new FourStateHandler(bundle, this); new LoadLongMsgAsyncTask(handler, getContext()).execute(chatItem.getContent()); } } private String getTimeWithFormat(int position) { ChatItem chatItem = getItem(position); String formatString = "MM月dd日 H时mm分"; SimpleDateFormat df = new SimpleDateFormat(formatString); if (position == 0) { return df.format(chatItem.getDate()); } else { ChatItem preItem = getItem(position - 1); if (chatItem.getDate().getTime() - preItem.getDate().getTime() > Constants.SHOW_DATE_TEXTVIEW_GAP) { return df.format(chatItem.getDate()); } else { return null; } } } public void setImageClickListener(ImageClickListener mImageClickListener) { this.mImageClickListener = mImageClickListener; } /* for server long msg items. */ @Override public void onStateIdle(int oldState, int newState, Bundle what) { int pos = what.getInt("pos"); ViewHolder viewHolder = mViewHolders.get(pos); viewHolder.progressBar.setVisibility(View.INVISIBLE); if (mLongMsgListener.get() != null) { mLongMsgListener.get().onLongMsgIdle(oldState, newState, what); } } @Override public void onStatePending(int oldState, int newState, Bundle what) { ViewHolder viewHolder = mViewHolders.get(what.getInt("pos")); viewHolder.progressBar.setVisibility(View.VISIBLE); if (mLongMsgListener.get() != null) { mLongMsgListener.get().onLongMsgPending(oldState, newState, what); } } @Override public void onStateSuccess(int oldState, int newState, Bundle what) { int pos = what.getInt("pos"); ChatItem item = getItem(pos); item.setType(ChatItemConstants.TYPE_SERVER); item.setContent(what.getString("response")); DBStaticManager.updateChatItem(getContext(), item); ViewHolder viewHolder = mViewHolders.get(pos); viewHolder.progressBar.setVisibility(View.INVISIBLE); viewHolder.chatTextView.setVisibility(View.VISIBLE); viewHolder.chatTextView.setText(item.getContent()); mLoadingItems.remove(what.getInt("pos")); notifyDataSetChanged(); if (mLongMsgListener.get() != null) { mLongMsgListener.get().onLongMsgSuccess(oldState, newState, what); } } @Override public void onStatefail(int oldState, int newState, Bundle what) { int pos = what.getInt("pos"); ViewHolder viewHolder = mViewHolders.get(pos); viewHolder.chatTextView.setVisibility(View.VISIBLE); viewHolder.chatTextView.setText(what.getString("err_msg")); mLoadingItems.remove(what.getInt("pos")); if (mLongMsgListener.get() != null) { mLongMsgListener.get().onLongMsgFail(oldState, newState, what); } } @Override public void onUnhandleState(int oldState, Bundle what) { Log.d(TAG, "unhandlerState: " + oldState + " what:" + what); } static class ViewHolder { ImageView imageView; TextView chatTextView; ProgressBar progressBar; RippleBackground rippleBackground; ImageButton errorButton; TextView dateTextView; } public enum ClickableImageType { IMAGE, LOCATION } /* * delegate */ public void setResendButtonClickListener( ResendButtonClickListener mResendButtonClickListener) { this.mResendButtonClickListener = mResendButtonClickListener; } public void setLongMsgListener(LongMsgListener listener) { this.mLongMsgListener = new WeakReference<LongMsgListener>(listener); } public interface ResendButtonClickListener { void onResendButtonClicked(int pos); } public interface ImageClickListener { void onImageViewClicked(Bundle bundle); void onImageViewLongClicked(String imageURL); } public interface LongMsgListener { void onLongMsgSuccess(int oldState, int newState, Bundle what); void onLongMsgFail(int oldState, int newState, Bundle what); void onLongMsgPending(int oldState, int newState, Bundle what); void onLongMsgIdle(int oldState, int newState, Bundle what); } }