From 380ead1a1d722e32d1cdb88d60ac4101d062084f Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Thu, 17 Sep 2020 22:07:21 +0800 Subject: Support swipe action in CommentAndPostRecyclerViewAdapter and CommentsListingRecyclerViewAdapter. --- .../Activity/ViewPostDetailActivity.java | 127 ++++++++++++++++++++- .../Adapter/CommentAndPostRecyclerViewAdapter.java | 21 +++- .../CommentsListingRecyclerViewAdapter.java | 13 ++- .../Adapter/PostRecyclerViewAdapter.java | 22 ++-- .../Fragment/CommentsListingFragment.java | 122 ++++++++++++++++++++ .../infinityforreddit/Fragment/PostFragment.java | 1 - 6 files changed, 287 insertions(+), 19 deletions(-) (limited to 'app/src/main') diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java index 9b34f58f..475d0001 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Activity/ViewPostDetailActivity.java @@ -1,10 +1,16 @@ package ml.docilealligator.infinityforreddit.Activity; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; +import android.os.VibrationEffect; +import android.os.Vibrator; import android.util.DisplayMetrics; import android.view.KeyEvent; import android.view.Menu; @@ -21,7 +27,9 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.drawable.DrawableCompat; +import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; @@ -93,6 +101,7 @@ import ml.docilealligator.infinityforreddit.SortType; import ml.docilealligator.infinityforreddit.SortTypeSelectionCallback; import ml.docilealligator.infinityforreddit.Utils.APIUtils; import ml.docilealligator.infinityforreddit.Utils.SharedPreferencesUtils; +import ml.docilealligator.infinityforreddit.Utils.Utils; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -211,6 +220,12 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS private SlidrInterface mSlidrInterface; private Drawable mSavedIcon; private Drawable mUnsavedIcon; + private ColorDrawable backgroundLeft; + private ColorDrawable backgroundRight; + private Drawable drawableLeft; + private Drawable drawableRight; + private float swipeActionThreshold = 0.3f; + private ItemTouchHelper touchHelper; @Override protected void onCreate(Bundle savedInstanceState) { @@ -279,6 +294,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS mExpandChildren = !mSharedPreferences.getBoolean(SharedPreferencesUtils.SHOW_TOP_LEVEL_COMMENTS_FIRST, false); mGlide = Glide.with(this); + Resources resources = getResources(); mLocale = getResources().getConfiguration().locale; mLinearLayoutManager = new LinearLayoutManager(this); @@ -362,6 +378,115 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS }); } + boolean enableSwipeAction = mSharedPreferences.getBoolean(SharedPreferencesUtils.ENABLE_SWIPE_ACTION, false); + boolean vibrateWhenActionTriggered = mSharedPreferences.getBoolean(SharedPreferencesUtils.VIBRATE_WHEN_ACTION_TRIGGERED, true); + Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); + backgroundLeft = new ColorDrawable(mCustomThemeWrapper.getDownvoted()); + backgroundRight = new ColorDrawable(mCustomThemeWrapper.getUpvoted()); + drawableLeft = ResourcesCompat.getDrawable(resources, R.drawable.ic_arrow_downward_black_24dp, null); + drawableRight = ResourcesCompat.getDrawable(resources, R.drawable.ic_arrow_upward_black_24dp, null); + touchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() { + boolean exceedThreshold = false; + + @Override + public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { + if (!(viewHolder instanceof CommentAndPostRecyclerViewAdapter.PostDetailBaseViewHolder) && + !(viewHolder instanceof CommentAndPostRecyclerViewAdapter.CommentViewHolder)) { + return makeMovementFlags(0, 0); + } + int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; + return makeMovementFlags(0, swipeFlags); + } + + @Override + public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) { + return false; + } + + @Override + public boolean isItemViewSwipeEnabled() { + return true; + } + + @Override + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { + if (touchHelper != null) { + touchHelper.attachToRecyclerView(null); + touchHelper.attachToRecyclerView(mRecyclerView); + if (mAdapter != null) { + mAdapter.onItemSwipe(viewHolder, direction); + } + } + } + + @Override + public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); + + View itemView = viewHolder.itemView; + int horizontalOffset = (int) Utils.convertDpToPixel(16, ViewPostDetailActivity.this); + if (dX > 0) { + if (dX > (itemView.getRight() - itemView.getLeft()) * swipeActionThreshold) { + if (!exceedThreshold) { + exceedThreshold = true; + if (vibrateWhenActionTriggered && v != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + v.vibrate(VibrationEffect.createOneShot(10, 175)); + } else { + //deprecated in API 26 + v.vibrate(10); + } + } + } + backgroundLeft.setBounds(0, itemView.getTop(), itemView.getRight(), itemView.getBottom()); + } else { + exceedThreshold = false; + backgroundLeft.setBounds(0, 0, 0, 0); + } + + drawableLeft.setBounds(itemView.getLeft() + ((int) dX) - horizontalOffset - drawableLeft.getIntrinsicWidth(), + (itemView.getBottom() + itemView.getTop() - drawableLeft.getIntrinsicHeight()) / 2, + itemView.getLeft() + ((int) dX) - horizontalOffset, + (itemView.getBottom() + itemView.getTop() + drawableLeft.getIntrinsicHeight()) / 2); + backgroundLeft.draw(c); + drawableLeft.draw(c); + } else if (dX < 0) { + if (-dX > (itemView.getRight() - itemView.getLeft()) * swipeActionThreshold) { + if (!exceedThreshold) { + exceedThreshold = true; + if (vibrateWhenActionTriggered && v != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + v.vibrate(VibrationEffect.createOneShot(10, 175)); + } else { + //deprecated in API 26 + v.vibrate(10); + } + } + } + backgroundRight.setBounds(0, itemView.getTop(), itemView.getRight(), itemView.getBottom()); + } else { + exceedThreshold = false; + backgroundRight.setBounds(0, 0, 0, 0); + } + drawableRight.setBounds(itemView.getRight() + ((int) dX) + horizontalOffset, + (itemView.getBottom() + itemView.getTop() - drawableRight.getIntrinsicHeight()) / 2, + itemView.getRight() + ((int) dX) + horizontalOffset + drawableRight.getIntrinsicWidth(), + (itemView.getBottom() + itemView.getTop() + drawableRight.getIntrinsicHeight()) / 2); + backgroundRight.draw(c); + drawableRight.draw(c); + } + } + + @Override + public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) { + return swipeActionThreshold; + } + }); + + if (enableSwipeAction) { + touchHelper.attachToRecyclerView(mRecyclerView); + } + mSwipeRefreshLayout.setOnRefreshListener(() -> refresh(true, true)); mSmoothScroller = new LinearSmoothScroller(this) { @@ -383,7 +508,7 @@ public class ViewPostDetailActivity extends BaseActivity implements FlairBottomS mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); } - orientation = getResources().getConfiguration().orientation; + orientation = resources.getConfiguration().orientation; if (!mNullAccessToken && mAccessToken == null) { getCurrentAccountAndBindView(); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java index 67447e0d..4874dd31 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Adapter/CommentAndPostRecyclerViewAdapter.java @@ -37,6 +37,7 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import androidx.core.graphics.drawable.DrawableCompat; +import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -1783,6 +1784,22 @@ public class CommentAndPostRecyclerViewAdapter extends RecyclerView.Adapter 0) { + if (dX > (itemView.getRight() - itemView.getLeft()) * swipeActionThreshold) { + if (!exceedThreshold) { + exceedThreshold = true; + if (vibrateWhenActionTriggered && v != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + v.vibrate(VibrationEffect.createOneShot(10, 175)); + } else { + //deprecated in API 26 + v.vibrate(10); + } + } + } + backgroundLeft.setBounds(0, itemView.getTop(), itemView.getRight(), itemView.getBottom()); + } else { + exceedThreshold = false; + backgroundLeft.setBounds(0, 0, 0, 0); + } + + drawableLeft.setBounds(itemView.getLeft() + ((int) dX) - horizontalOffset - drawableLeft.getIntrinsicWidth(), + (itemView.getBottom() + itemView.getTop() - drawableLeft.getIntrinsicHeight()) / 2, + itemView.getLeft() + ((int) dX) - horizontalOffset, + (itemView.getBottom() + itemView.getTop() + drawableLeft.getIntrinsicHeight()) / 2); + backgroundLeft.draw(c); + drawableLeft.draw(c); + } else if (dX < 0) { + if (-dX > (itemView.getRight() - itemView.getLeft()) * swipeActionThreshold) { + if (!exceedThreshold) { + exceedThreshold = true; + if (vibrateWhenActionTriggered && v != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + v.vibrate(VibrationEffect.createOneShot(10, 175)); + } else { + //deprecated in API 26 + v.vibrate(10); + } + } + } + backgroundRight.setBounds(0, itemView.getTop(), itemView.getRight(), itemView.getBottom()); + } else { + exceedThreshold = false; + backgroundRight.setBounds(0, 0, 0, 0); + } + drawableRight.setBounds(itemView.getRight() + ((int) dX) + horizontalOffset, + (itemView.getBottom() + itemView.getTop() - drawableRight.getIntrinsicHeight()) / 2, + itemView.getRight() + ((int) dX) + horizontalOffset + drawableRight.getIntrinsicWidth(), + (itemView.getBottom() + itemView.getTop() + drawableRight.getIntrinsicHeight()) / 2); + backgroundRight.draw(c); + drawableRight.draw(c); + } + } + + @Override + public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) { + return swipeActionThreshold; + } + }); + + if (enableSwipeAction) { + touchHelper.attachToRecyclerView(mCommentRecyclerView); + } + if (savedInstanceState == null) { getCurrentAccountAndBindView(resources); } else { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java index 37264783..f6361088 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/Fragment/PostFragment.java @@ -635,7 +635,6 @@ public class PostFragment extends Fragment implements FragmentCommunicator { } Vibrator v = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); - // Vibrate for 500 milliseconds backgroundLeft = new ColorDrawable(customThemeWrapper.getDownvoted()); backgroundRight = new ColorDrawable(customThemeWrapper.getUpvoted()); drawableLeft = ResourcesCompat.getDrawable(activity.getResources(), R.drawable.ic_arrow_downward_black_24dp, null); -- cgit v1.2.3