From bf2d0d5596a08872230056d056241ee906962171 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 25 Apr 2014 16:24:56 +0200 Subject: smoother scrolling (first step) --- .../conversations/ui/ConversationActivity.java | 138 ++++++++++++++++++++- .../conversations/ui/ConversationFragment.java | 60 ++++----- 2 files changed, 165 insertions(+), 33 deletions(-) (limited to 'src/eu/siacs/conversations/ui') diff --git a/src/eu/siacs/conversations/ui/ConversationActivity.java b/src/eu/siacs/conversations/ui/ConversationActivity.java index 41d9ad0fd..32e3588b2 100644 --- a/src/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/eu/siacs/conversations/ui/ConversationActivity.java @@ -1,5 +1,7 @@ package eu.siacs.conversations.ui; +import java.io.FileNotFoundException; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -11,20 +13,26 @@ import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.utils.ExceptionHelper; import eu.siacs.conversations.utils.UIHelper; +import android.os.AsyncTask; import android.os.Bundle; import android.preference.PreferenceManager; import android.app.AlertDialog; -import android.app.AlertDialog.Builder; import android.app.FragmentTransaction; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; +import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.support.v4.widget.SlidingPaneLayout; import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener; +import android.util.DisplayMetrics; +import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -57,7 +65,7 @@ public class ConversationActivity extends XmppActivity { private List conversationList = new ArrayList(); private Conversation selectedConversation = null; private ListView listView; - + private boolean paneShouldBeOpen = true; private boolean useSubject = true; private ArrayAdapter listAdapter; @@ -91,6 +99,7 @@ public class ConversationActivity extends XmppActivity { }; protected ConversationActivity activity = this; + private DisplayMetrics metrics; public List getConversationList() { return this.conversationList; @@ -115,6 +124,8 @@ public class ConversationActivity extends XmppActivity { @Override protected void onCreate(Bundle savedInstanceState) { + metrics = getResources().getDisplayMetrics(); + super.onCreate(savedInstanceState); setContentView(R.layout.fragment_conversations_overview); @@ -150,7 +161,35 @@ public class ConversationActivity extends XmppActivity { convName.setText(conv.getName(useSubject)); TextView convLastMsg = (TextView) view .findViewById(R.id.conversation_lastmsg); - convLastMsg.setText(conv.getLatestMessage().getBody()); + ImageView imagePreview = (ImageView) view.findViewById(R.id.conversation_lastimage); + + Message latestMessage = conv.getLatestMessage(); + + if (latestMessage.getType() == Message.TYPE_TEXT) { + convLastMsg.setText(conv.getLatestMessage().getBody()); + convLastMsg.setVisibility(View.VISIBLE); + imagePreview.setVisibility(View.GONE); + } else if (latestMessage.getType() == Message.TYPE_IMAGE) { + if ((latestMessage.getStatus() >= Message.STATUS_RECIEVED)&&(latestMessage.getStatus() != Message.STATUS_PREPARING)) { + convLastMsg.setVisibility(View.GONE); + imagePreview.setVisibility(View.VISIBLE); + loadBitmap(latestMessage, imagePreview); + } else { + convLastMsg.setVisibility(View.VISIBLE); + imagePreview.setVisibility(View.GONE); + if (latestMessage.getStatus() == Message.STATUS_PREPARING) { + convLastMsg.setText(getText(R.string.preparing_image)); + } else if (latestMessage.getStatus() == Message.STATUS_RECEIVED_OFFER) { + convLastMsg.setText(getText(R.string.image_offered_for_download)); + } else if (latestMessage.getStatus() == Message.STATUS_RECIEVING) { + convLastMsg.setText(getText(R.string.receiving_image)); + } else { + convLastMsg.setText(""); + } + } + } + + if (!conv.isRead()) { convName.setTypeface(null, Typeface.BOLD); @@ -164,10 +203,11 @@ public class ConversationActivity extends XmppActivity { .setText(UIHelper.readableTimeDifference(conv .getLatestMessage().getTimeSent())); - ImageView imageView = (ImageView) view + ImageView profilePicture = (ImageView) view .findViewById(R.id.conversation_image); - imageView.setImageBitmap(UIHelper.getContactPicture( + profilePicture.setImageBitmap(UIHelper.getContactPicture( conv, 56, activity.getApplicationContext(), false)); + return view; } @@ -602,4 +642,92 @@ public class ConversationActivity extends XmppActivity { }); builder.create().show(); } + + + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private Message message = null; + + public BitmapWorkerTask(ImageView imageView) { + // Use a WeakReference to ensure the ImageView can be garbage collected + imageViewReference = new WeakReference(imageView); + } + + // Decode image in background. + @Override + protected Bitmap doInBackground(Message... params) { + message = params[0]; + try { + return xmppConnectionService.getFileBackend().getThumbnail(message, (int) (metrics.density * 288)); + } catch (FileNotFoundException e) { + Log.d("xmppService","file not found!"); + return null; + } + } + + // Once complete, see if ImageView is still around and set bitmap. + @Override + protected void onPostExecute(Bitmap bitmap) { + if (imageViewReference != null && bitmap != null) { + final ImageView imageView = imageViewReference.get(); + if (imageView != null) { + imageView.setImageBitmap(bitmap); + } + } + } + } + + public void loadBitmap(Message message, ImageView imageView) { + if (cancelPotentialWork(message, imageView)) { + final BitmapWorkerTask task = new BitmapWorkerTask(imageView); + final AsyncDrawable asyncDrawable = + new AsyncDrawable(getResources(), null, task); + imageView.setImageDrawable(asyncDrawable); + task.execute(message); + } + } + + public static boolean cancelPotentialWork(Message message, ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final Message oldMessage = bitmapWorkerTask.message; + // If bitmapData is not yet set or it differs from the new data + if (oldMessage == null || message != oldMessage) { + // Cancel previous task + bitmapWorkerTask.cancel(true); + } else { + // The same work is already in progress + return false; + } + } + // No task associated with the ImageView, or an existing task was cancelled + return true; + } + + private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { + if (imageView != null) { + final Drawable drawable = imageView.getDrawable(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + + static class AsyncDrawable extends BitmapDrawable { + private final WeakReference bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, + BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = + new WeakReference(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } } diff --git a/src/eu/siacs/conversations/ui/ConversationFragment.java b/src/eu/siacs/conversations/ui/ConversationFragment.java index a4259f273..d42b33c4a 100644 --- a/src/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/eu/siacs/conversations/ui/ConversationFragment.java @@ -297,27 +297,38 @@ public class ConversationFragment extends Fragment { } }); } else { - try { - Bitmap thumbnail = activity.xmppConnectionService.getFileBackend().getThumbnailFromMessage(item,(int) (metrics.density * 288)); - viewHolder.image.setImageBitmap(thumbnail); - viewHolder.messageBody.setVisibility(View.GONE); - viewHolder.image.setVisibility(View.VISIBLE); - viewHolder.image.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - Uri uri = Uri.parse("content://eu.siacs.conversations.images/"+item.getConversationUuid()+"/"+item.getUuid()); - Log.d("xmppService","staring intent with uri:"+uri.toString()); - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(uri, "image/*"); - startActivity(intent); - } - }); - } catch (FileNotFoundException e) { - viewHolder.image.setVisibility(View.GONE); - viewHolder.messageBody.setText("error loading image file"); - viewHolder.messageBody.setVisibility(View.VISIBLE); - } + viewHolder.messageBody.setVisibility(View.GONE); + viewHolder.image.setVisibility(View.VISIBLE); + String[] params = item.getBody().split(","); + if (params.length==3) { + int target = (int) (metrics.density * 288); + int w = Integer.parseInt(params[1]); + int h = Integer.parseInt(params[2]); + int scalledW; + int scalledH; + if (w <= h) { + scalledW = (int) (w / ((double) h / target)); + scalledH = target; + } else { + scalledW = target; + scalledH = (int) (h / ((double) w / target)); + } + viewHolder.image.setLayoutParams(new LinearLayout.LayoutParams(scalledW, scalledH)); + } else { + Log.d("xmppService","message body has less than 3 params"); + } + activity.loadBitmap(item, viewHolder.image); + viewHolder.image.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + Uri uri = Uri.parse("content://eu.siacs.conversations.images/"+item.getConversationUuid()+"/"+item.getUuid()); + Log.d("xmppService","staring intent with uri:"+uri.toString()); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(uri, "image/*"); + startActivity(intent); + } + }); } } else { viewHolder.image.setVisibility(View.GONE); @@ -686,13 +697,6 @@ public class ConversationFragment extends Fragment { return bm; } } - - public Bitmap getError() { - if (error == null) { - error = UIHelper.getErrorPicture(200); - } - return error; - } } class DecryptMessage extends AsyncTask { -- cgit v1.2.3