diff --git a/res/drawable-hdpi/ic_scroll_down.png b/res/drawable-hdpi/ic_scroll_down.png new file mode 100644 index 0000000000..5d23096c4d Binary files /dev/null and b/res/drawable-hdpi/ic_scroll_down.png differ diff --git a/res/drawable-mdpi/ic_scroll_down.png b/res/drawable-mdpi/ic_scroll_down.png new file mode 100644 index 0000000000..2b570d6823 Binary files /dev/null and b/res/drawable-mdpi/ic_scroll_down.png differ diff --git a/res/drawable-xhdpi/ic_scroll_down.png b/res/drawable-xhdpi/ic_scroll_down.png new file mode 100644 index 0000000000..a3e1b8cf74 Binary files /dev/null and b/res/drawable-xhdpi/ic_scroll_down.png differ diff --git a/res/drawable-xxhdpi/ic_scroll_down.png b/res/drawable-xxhdpi/ic_scroll_down.png new file mode 100644 index 0000000000..4f3df9bb81 Binary files /dev/null and b/res/drawable-xxhdpi/ic_scroll_down.png differ diff --git a/res/drawable-xxxhdpi/ic_scroll_down.png b/res/drawable-xxxhdpi/ic_scroll_down.png new file mode 100644 index 0000000000..569715e0a9 Binary files /dev/null and b/res/drawable-xxxhdpi/ic_scroll_down.png differ diff --git a/res/layout/conversation_fragment.xml b/res/layout/conversation_fragment.xml index 9204d31a2c..042b677466 100644 --- a/res/layout/conversation_fragment.xml +++ b/res/layout/conversation_fragment.xml @@ -2,7 +2,8 @@ + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 3fa139d1b3..72b4318cdd 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -66,7 +66,4 @@ 20sp 3dp - - 10dp - 10dp diff --git a/src/org/thoughtcrime/securesms/ConversationFragment.java b/src/org/thoughtcrime/securesms/ConversationFragment.java index 69d2f061a6..9193587d67 100644 --- a/src/org/thoughtcrime/securesms/ConversationFragment.java +++ b/src/org/thoughtcrime/securesms/ConversationFragment.java @@ -24,6 +24,7 @@ import android.database.Cursor; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; @@ -44,6 +45,8 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.Window; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; import android.widget.Toast; import org.thoughtcrime.securesms.ConversationAdapter.ItemClickListener; @@ -79,7 +82,6 @@ public class ConversationFragment extends Fragment private final ActionModeCallback actionModeCallback = new ActionModeCallback(); private final ItemClickListener selectionClickListener = new ConversationFragmentItemClickListener(); - private final OnScrollListener scrollListener = new ConversationScrollListener(); private ConversationFragmentListener listener; @@ -117,7 +119,6 @@ public class ConversationFragment extends Fragment final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, true); list.setHasFixedSize(false); list.setLayoutManager(layoutManager); - list.addOnScrollListener(scrollListener); list.setItemAnimator(null); loadMoreView = inflater.inflate(R.layout.load_more_header, container, false); @@ -173,8 +174,11 @@ public class ConversationFragment extends Fragment } private void initializeResources() { - this.recipients = RecipientFactory.getRecipientsForIds(getActivity(), getActivity().getIntent().getLongArrayExtra("recipients"), true); - this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1); + this.recipients = RecipientFactory.getRecipientsForIds(getActivity(), getActivity().getIntent().getLongArrayExtra("recipients"), true); + this.threadId = this.getActivity().getIntent().getLongExtra("thread_id", -1); + + OnScrollListener scrollListener = new ConversationScrollListener(getActivity()); + list.addOnScrollListener(scrollListener); } private void initializeListAdapter() { @@ -408,26 +412,39 @@ public class ConversationFragment extends Fragment } private class ConversationScrollListener extends OnScrollListener { - private boolean wasAtBottom = true; + + private final Animation scrollButtonInAnimation; + private final Animation scrollButtonOutAnimation; + + private boolean wasAtBottom = true; + private boolean wasAtZoomScrollHeight = false; + + ConversationScrollListener(@NonNull Context context) { + this.scrollButtonInAnimation = AnimationUtils.loadAnimation(context, R.anim.fade_scale_in); + this.scrollButtonOutAnimation = AnimationUtils.loadAnimation(context, R.anim.fade_scale_out); + + this.scrollButtonInAnimation.setDuration(100); + this.scrollButtonOutAnimation.setDuration(50); + } @Override public void onScrolled(final RecyclerView rv, final int dx, final int dy) { - boolean currentlyAtBottom = isAtBottom(); + boolean currentlyAtBottom = isAtBottom(); + boolean currentlyAtZoomScrollHeight = isAtZoomScrollHeight(); - if (wasAtBottom != currentlyAtBottom) { - composeDivider.setVisibility(currentlyAtBottom ? View.INVISIBLE : View.VISIBLE); - scrollToBottomButton.setVisibility(currentlyAtBottom ? View.INVISIBLE : View.VISIBLE); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) { - composeDivider.animate().alpha(currentlyAtBottom ? 0 : 1); - scrollToBottomButton.animate().alpha(currentlyAtBottom ? 0 : 1); - } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) { - composeDivider.setAlpha(currentlyAtBottom ? 0 : 1); - scrollToBottomButton.setAlpha(currentlyAtBottom ? 0 : 1); - } - - wasAtBottom = currentlyAtBottom; + if (currentlyAtBottom && !wasAtBottom) { + ViewUtil.fadeOut(composeDivider, 50, View.INVISIBLE); + ViewUtil.animateOut(scrollToBottomButton, scrollButtonOutAnimation, View.INVISIBLE); + } else if (!currentlyAtBottom && wasAtBottom) { + ViewUtil.fadeIn(composeDivider, 500); } + + if (currentlyAtZoomScrollHeight && !wasAtZoomScrollHeight) { + ViewUtil.animateIn(scrollToBottomButton, scrollButtonInAnimation); + } + + wasAtBottom = currentlyAtBottom; + wasAtZoomScrollHeight = currentlyAtZoomScrollHeight; } private boolean isAtBottom() { @@ -439,6 +456,10 @@ public class ConversationFragment extends Fragment return isAtBottom && bottomView.getBottom() <= list.getHeight(); } + + private boolean isAtZoomScrollHeight() { + return ((LinearLayoutManager) list.getLayoutManager()).findFirstCompletelyVisibleItemPosition() > 4; + } } private class ConversationFragmentItemClickListener implements ItemClickListener {