aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDocile-Alligator <25734209+Docile-Alligator@users.noreply.github.com>2023-04-26 07:36:21 +0000
committerDocile-Alligator <25734209+Docile-Alligator@users.noreply.github.com>2023-04-26 07:36:21 +0000
commitef4ead043410cf638d33325fe6a250ddc94c6d02 (patch)
treebf65712b80b0119bde69c52f6b05d9615ab74d60
parentb885e12d1a4c21ff965e9b45c1e4bd29dc010420 (diff)
downloadinfinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.tar
infinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.tar.gz
infinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.tar.bz2
infinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.tar.lz
infinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.tar.xz
infinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.tar.zst
infinity-for-reddit-ef4ead043410cf638d33325fe6a250ddc94c6d02.zip
Include Slidr in code.
-rw-r--r--app/build.gradle1
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountPostsActivity.java17
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountSavedThingActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/CreateMultiRedditActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemePreviewActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditMultiRedditActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java4
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditProfileActivity.java9
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/FilteredPostsActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/GiveAwardActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/HistoryActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/InboxActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/MultiredditSelectionActivity.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ReportActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/RulesActivity.java18
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchActivity.java4
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchResultActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchSubredditsResultActivity.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchUsersResultActivity.java3
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectUserFlairActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectedSubredditsAndUsersActivity.java6
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditMultiselectionActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditSelectionActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubscribedThingListingActivity.java18
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java6
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewMultiRedditDetailActivity.java2
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java17
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java18
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java19
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java16
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java17
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ColorPanelSlideListener.java68
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ConfigPanelSlideListener.java68
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/FragmentPanelSlideListener.java67
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/Slidr.java133
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrConfig.java318
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrInterface.java8
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListener.java31
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListenerAdapter.java22
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrPosition.java12
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/util/ViewDragHelper.java1404
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/ScrimRenderer.java125
-rw-r--r--app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/SliderPanel.java782
-rw-r--r--app/src/main/res/values-es/strings.xml2
-rw-r--r--app/src/main/res/values-vi/strings.xml6
-rw-r--r--app/src/main/res/values/ids.xml5
50 files changed, 3192 insertions, 158 deletions
diff --git a/app/build.gradle b/app/build.gradle
index b60bad1e..68528c97 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -176,7 +176,6 @@ dependencies {
implementation 'com.libRG:customtextview:2.4'
// Dismiss gesturing
- implementation 'com.r0adkll:slidableactivity:2.1.0'
implementation 'app.futured.hauler:hauler:5.0.0'
// Bottom sheet with rounded corners
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountPostsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountPostsActivity.java
index 7a7a77eb..0edd6a38 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountPostsActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountPostsActivity.java
@@ -12,9 +12,6 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
-
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -29,6 +26,8 @@ import ml.docilealligator.infinityforreddit.SortType;
import ml.docilealligator.infinityforreddit.SortTypeSelectionCallback;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.PostLayoutBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.databinding.ActivityAccountPostsBinding;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
@@ -54,7 +53,7 @@ public class AccountPostsActivity extends BaseActivity implements SortTypeSelect
SharedPreferences mCurrentAccountSharedPreferences;
@Inject
CustomThemeWrapper mCustomThemeWrapper;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private String mAccessToken;
private String mAccountName;
private String mUserWhere;
@@ -76,7 +75,7 @@ public class AccountPostsActivity extends BaseActivity implements SortTypeSelect
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -244,15 +243,15 @@ public class AccountPostsActivity extends BaseActivity implements SortTypeSelect
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountSavedThingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountSavedThingActivity.java
index 90364417..0e60f2d1 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountSavedThingActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/AccountSavedThingActivity.java
@@ -18,8 +18,6 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayoutMediator;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -36,6 +34,8 @@ import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.PostLayoutBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.databinding.ActivityAccountSavedThingBinding;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
@@ -71,7 +71,7 @@ public class AccountSavedThingActivity extends BaseActivity implements ActivityT
Executor mExecutor;
private FragmentManager fragmentManager;
private SectionsPagerAdapter sectionsPagerAdapter;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private String mAccessToken;
private String mAccountName;
private PostLayoutBottomSheetFragment postLayoutBottomSheetFragment;
@@ -90,7 +90,7 @@ public class AccountSavedThingActivity extends BaseActivity implements ActivityT
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -231,15 +231,15 @@ public class AccountSavedThingActivity extends BaseActivity implements ActivityT
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CreateMultiRedditActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CreateMultiRedditActivity.java
index ff62df44..9bc280e2 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CreateMultiRedditActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CreateMultiRedditActivity.java
@@ -22,7 +22,6 @@ import androidx.core.view.inputmethod.EditorInfoCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.snackbar.Snackbar;
-import com.r0adkll.slidr.Slidr;
import java.util.ArrayList;
import java.util.concurrent.Executor;
@@ -36,6 +35,7 @@ import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.multireddit.CreateMultiReddit;
import ml.docilealligator.infinityforreddit.multireddit.MultiRedditJSONModel;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemePreviewActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemePreviewActivity.java
index 19b687ad..3a603952 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemePreviewActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomThemePreviewActivity.java
@@ -39,8 +39,6 @@ import com.google.android.material.bottomappbar.BottomAppBar;
import com.google.android.material.chip.Chip;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import java.util.ArrayList;
@@ -56,6 +54,8 @@ import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.customtheme.CustomTheme;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeSettingsItem;
import ml.docilealligator.infinityforreddit.customviews.ViewPagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.font.ContentFontStyle;
import ml.docilealligator.infinityforreddit.font.FontStyle;
import ml.docilealligator.infinityforreddit.font.TitleFontStyle;
@@ -126,7 +126,7 @@ public class CustomThemePreviewActivity extends AppCompatActivity implements Cus
private int subscribedColor;
private int systemVisibilityToolbarExpanded = 0;
private int systemVisibilityToolbarCollapsed = 0;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -232,7 +232,7 @@ public class CustomThemePreviewActivity extends AppCompatActivity implements Cus
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -453,14 +453,14 @@ public class CustomThemePreviewActivity extends AppCompatActivity implements Cus
}
private void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
private void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java
index 5721cc50..45097020 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/CustomizePostFilterActivity.java
@@ -30,7 +30,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
-import com.r0adkll.slidr.Slidr;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -47,6 +46,7 @@ import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.postfilter.PostFilter;
import ml.docilealligator.infinityforreddit.postfilter.SavePostFilter;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditMultiRedditActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditMultiRedditActivity.java
index 0a7cfb4f..ab214588 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditMultiRedditActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditMultiRedditActivity.java
@@ -24,7 +24,6 @@ import androidx.core.view.inputmethod.EditorInfoCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.snackbar.Snackbar;
-import com.r0adkll.slidr.Slidr;
import java.util.concurrent.Executor;
@@ -37,6 +36,7 @@ import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.multireddit.EditMultiReddit;
import ml.docilealligator.infinityforreddit.multireddit.FetchMultiRedditInfo;
import ml.docilealligator.infinityforreddit.multireddit.MultiReddit;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java
index c0960421..5e022426 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditPostActivity.java
@@ -1,7 +1,6 @@
package ml.docilealligator.infinityforreddit.activities;
import android.content.ActivityNotFoundException;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
@@ -13,7 +12,6 @@ import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@@ -28,7 +26,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -54,6 +51,7 @@ import ml.docilealligator.infinityforreddit.apis.RedditAPI;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.UploadedImagesBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditProfileActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditProfileActivity.java
index 25531633..56cd48ce 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditProfileActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/EditProfileActivity.java
@@ -29,8 +29,6 @@ import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -45,6 +43,9 @@ import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.SubmitChangeAvatarEvent;
import ml.docilealligator.infinityforreddit.events.SubmitChangeBannerEvent;
import ml.docilealligator.infinityforreddit.events.SubmitSaveProfileEvent;
@@ -123,8 +124,8 @@ public class EditProfileActivity extends BaseActivity {
setSupportActionBar(toolbar);
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- SlidrInterface slidrInterface = Slidr.attach(this);
- slidrInterface.unlock();
+ SliderPanel sliderPanel = Slidr.attach(this);
+ sliderPanel.unlock();
}
mAccessToken = mCurrentAccountSharedPreferences.getString(SharedPreferencesUtils.ACCESS_TOKEN, null);
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FilteredPostsActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FilteredPostsActivity.java
index 4f60003b..28d6c177 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FilteredPostsActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FilteredPostsActivity.java
@@ -18,7 +18,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -46,6 +45,7 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTimeBottomS
import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTypeBottomSheetFragment;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.UserThingSortTypeBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.PostFragment;
import ml.docilealligator.infinityforreddit.post.Post;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java
index bf1b3566..4a4477ac 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/FullMarkdownActivity.java
@@ -20,8 +20,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -43,6 +41,8 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
@@ -68,7 +68,7 @@ public class FullMarkdownActivity extends BaseActivity {
SharedPreferences mSharedPreferences;
@Inject
CustomThemeWrapper mCustomThemeWrapper;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -89,7 +89,7 @@ public class FullMarkdownActivity extends BaseActivity {
setTitle(" ");
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -147,15 +147,15 @@ public class FullMarkdownActivity extends BaseActivity {
LinearLayoutManagerBugFixed linearLayoutManager = new SwipeLockLinearLayoutManager(this, new SwipeLockInterface() {
@Override
public void lockSwipe() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipe() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
});
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/GiveAwardActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/GiveAwardActivity.java
index 971e0b19..8803e96a 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/GiveAwardActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/GiveAwardActivity.java
@@ -22,7 +22,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.materialswitch.MaterialSwitch;
-import com.r0adkll.slidr.Slidr;
import java.util.concurrent.Executor;
@@ -38,6 +37,7 @@ import ml.docilealligator.infinityforreddit.adapters.AwardRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.award.GiveAward;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import retrofit2.Retrofit;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/HistoryActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/HistoryActivity.java
index 3a2b5265..a8f1e440 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/HistoryActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/HistoryActivity.java
@@ -23,8 +23,6 @@ import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.tabs.TabLayout;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -39,6 +37,8 @@ import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.PostLayoutBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.CommentsListingFragment;
@@ -74,7 +74,7 @@ public class HistoryActivity extends BaseActivity implements ActivityToolbarInte
CustomThemeWrapper mCustomThemeWrapper;
private FragmentManager fragmentManager;
private SectionsPagerAdapter sectionsPagerAdapter;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private String mAccessToken;
private String mAccountName;
@@ -93,7 +93,7 @@ public class HistoryActivity extends BaseActivity implements ActivityToolbarInte
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -229,15 +229,15 @@ public class HistoryActivity extends BaseActivity implements ActivityToolbarInte
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/InboxActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/InboxActivity.java
index eed1d64f..b2314e5b 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/InboxActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/InboxActivity.java
@@ -30,8 +30,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.android.material.textfield.TextInputEditText;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -51,6 +49,8 @@ import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.apis.RedditAPI;
import ml.docilealligator.infinityforreddit.asynctasks.SwitchAccount;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.ChangeInboxCountEvent;
import ml.docilealligator.infinityforreddit.events.PassPrivateMessageEvent;
import ml.docilealligator.infinityforreddit.events.PassPrivateMessageIndexEvent;
@@ -103,7 +103,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
CustomThemeWrapper mCustomThemeWrapper;
@Inject
Executor mExecutor;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private SectionsPagerAdapter sectionsPagerAdapter;
private FragmentManager fragmentManager;
private String mAccessToken;
@@ -125,7 +125,7 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -381,15 +381,15 @@ public class InboxActivity extends BaseActivity implements ActivityToolbarInterf
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginActivity.java
index 552dbca9..832885b9 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginActivity.java
@@ -28,7 +28,6 @@ import androidx.core.app.ActivityCompat;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.r0adkll.slidr.Slidr;
import org.json.JSONException;
import org.json.JSONObject;
@@ -50,6 +49,7 @@ import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.apis.RedditAPI;
import ml.docilealligator.infinityforreddit.asynctasks.ParseAndInsertNewAccount;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.utils.APIUtils;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MultiredditSelectionActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MultiredditSelectionActivity.java
index 2acc7da4..d3214f50 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MultiredditSelectionActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MultiredditSelectionActivity.java
@@ -7,7 +7,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
-import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
@@ -19,7 +18,6 @@ import androidx.fragment.app.Fragment;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -38,6 +36,7 @@ import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.asynctasks.InsertMultireddit;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.MultiRedditListingFragment;
import ml.docilealligator.infinityforreddit.multireddit.FetchMyMultiReddits;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ReportActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ReportActivity.java
index f3265367..8ef82bd6 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ReportActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ReportActivity.java
@@ -15,7 +15,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.snackbar.Snackbar;
-import com.r0adkll.slidr.Slidr;
import java.util.ArrayList;
import java.util.concurrent.Executor;
@@ -34,6 +33,7 @@ import ml.docilealligator.infinityforreddit.ReportThing;
import ml.docilealligator.infinityforreddit.Rule;
import ml.docilealligator.infinityforreddit.adapters.ReportReasonRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import retrofit2.Retrofit;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/RulesActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/RulesActivity.java
index a33bdde0..e7923cd6 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/RulesActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/RulesActivity.java
@@ -11,7 +11,6 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;
-import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
@@ -20,8 +19,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -34,13 +31,16 @@ import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
-import ml.docilealligator.infinityforreddit.adapters.RulesRecyclerViewAdapter;
-import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
-import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.FetchRules;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.Rule;
+import ml.docilealligator.infinityforreddit.adapters.RulesRecyclerViewAdapter;
+import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
+import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import retrofit2.Retrofit;
@@ -98,9 +98,9 @@ public class RulesActivity extends BaseActivity {
applyCustomTheme();
- SlidrInterface slidrInterface = null;
+ SliderPanel sliderPanel = null;
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- slidrInterface = Slidr.attach(this);
+ sliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -132,7 +132,7 @@ public class RulesActivity extends BaseActivity {
mSubredditName = getIntent().getExtras().getString(EXTRA_SUBREDDIT_NAME);
- mAdapter = new RulesRecyclerViewAdapter(this, mCustomThemeWrapper, slidrInterface);
+ mAdapter = new RulesRecyclerViewAdapter(this, mCustomThemeWrapper, sliderPanel);
recyclerView.setAdapter(mAdapter);
FetchRules.fetchRules(mExecutor, new Handler(), mAccessToken == null ? mRetrofit : mOauthRetrofit, mAccessToken, mSubredditName, new FetchRules.FetchRulesListener() {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchActivity.java
index 788567fc..4bf0bcfa 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchActivity.java
@@ -1,7 +1,6 @@
package ml.docilealligator.infinityforreddit.activities;
import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
@@ -14,7 +13,6 @@ import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
@@ -29,7 +27,6 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -48,6 +45,7 @@ import ml.docilealligator.infinityforreddit.adapters.SearchActivityRecyclerViewA
import ml.docilealligator.infinityforreddit.adapters.SubredditAutocompleteRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.apis.RedditAPI;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.recentsearchquery.DeleteRecentSearchQuery;
import ml.docilealligator.infinityforreddit.recentsearchquery.RecentSearchQuery;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchResultActivity.java
index 670411b8..d228bd65 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchResultActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchResultActivity.java
@@ -33,8 +33,6 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.android.material.textfield.TextInputEditText;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -64,6 +62,8 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.SearchPostSortT
import ml.docilealligator.infinityforreddit.bottomsheetfragments.SearchUserAndSubredditSortTypeBottomSheetFragment;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTimeBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.PostFragment;
@@ -138,7 +138,7 @@ public class SearchResultActivity extends BaseActivity implements SortTypeSelect
private boolean mInsertSearchQuerySuccess;
private FragmentManager fragmentManager;
private SectionsPagerAdapter sectionsPagerAdapter;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private int fabOption;
@Override
@@ -156,7 +156,7 @@ public class SearchResultActivity extends BaseActivity implements SortTypeSelect
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -904,15 +904,15 @@ public class SearchResultActivity extends BaseActivity implements SortTypeSelect
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchSubredditsResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchSubredditsResultActivity.java
index 9ba6a65e..bef51c3e 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchSubredditsResultActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchSubredditsResultActivity.java
@@ -7,7 +7,6 @@ import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -17,7 +16,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment;
import com.google.android.material.appbar.AppBarLayout;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -33,6 +31,7 @@ import ml.docilealligator.infinityforreddit.ActivityToolbarInterface;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.SubredditListingFragment;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchUsersResultActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchUsersResultActivity.java
index f6fde472..122ee34c 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchUsersResultActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SearchUsersResultActivity.java
@@ -7,7 +7,6 @@ import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
import android.view.Window;
import android.view.WindowManager;
@@ -17,7 +16,6 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment;
import com.google.android.material.appbar.AppBarLayout;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -33,6 +31,7 @@ import ml.docilealligator.infinityforreddit.ActivityToolbarInterface;
import ml.docilealligator.infinityforreddit.Infinity;
import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.UserListingFragment;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectUserFlairActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectUserFlairActivity.java
index 5287c47c..82cb3198 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectUserFlairActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectUserFlairActivity.java
@@ -18,7 +18,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
-import com.r0adkll.slidr.Slidr;
import java.util.ArrayList;
@@ -36,6 +35,7 @@ import ml.docilealligator.infinityforreddit.UserFlair;
import ml.docilealligator.infinityforreddit.adapters.UserFlairRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import retrofit2.Retrofit;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectedSubredditsAndUsersActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectedSubredditsAndUsersActivity.java
index bbe6e6b4..80ac0828 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectedSubredditsAndUsersActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SelectedSubredditsAndUsersActivity.java
@@ -16,7 +16,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
-import com.r0adkll.slidr.Slidr;
import java.util.ArrayList;
import java.util.Collections;
@@ -27,12 +26,13 @@ import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
import ml.docilealligator.infinityforreddit.ActivityToolbarInterface;
+import ml.docilealligator.infinityforreddit.Infinity;
+import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.adapters.SelectedSubredditsRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.SelectSubredditsOrUsersOptionsBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
-import ml.docilealligator.infinityforreddit.Infinity;
-import ml.docilealligator.infinityforreddit.R;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
public class SelectedSubredditsAndUsersActivity extends BaseActivity implements ActivityToolbarInterface {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditMultiselectionActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditMultiselectionActivity.java
index 555722f5..0a36fe79 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditMultiselectionActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditMultiselectionActivity.java
@@ -25,7 +25,6 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
import java.util.ArrayList;
@@ -41,6 +40,7 @@ import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.adapters.SubredditMultiselectionRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.subscribedsubreddit.SubscribedSubredditViewModel;
import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import retrofit2.Retrofit;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditSelectionActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditSelectionActivity.java
index ef3a2c4f..0fe3a7f6 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditSelectionActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubredditSelectionActivity.java
@@ -19,7 +19,6 @@ import androidx.fragment.app.Fragment;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -42,6 +41,7 @@ import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
import ml.docilealligator.infinityforreddit.account.Account;
import ml.docilealligator.infinityforreddit.asynctasks.InsertSubscribedThings;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.SubscribedSubredditsListingFragment;
import ml.docilealligator.infinityforreddit.subreddit.SubredditData;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubscribedThingListingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubscribedThingListingActivity.java
index 1faf7022..22dbd508 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubscribedThingListingActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/SubscribedThingListingActivity.java
@@ -32,8 +32,6 @@ import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.tabs.TabLayout;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -57,6 +55,8 @@ import ml.docilealligator.infinityforreddit.asynctasks.InsertMultireddit;
import ml.docilealligator.infinityforreddit.asynctasks.InsertSubscribedThings;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.ViewPagerBugFixed;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.GoBackToMainPageEvent;
import ml.docilealligator.infinityforreddit.events.RefreshMultiRedditsEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
@@ -73,6 +73,8 @@ import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
import ml.docilealligator.infinityforreddit.utils.Utils;
import retrofit2.Retrofit;
+;
+
public class SubscribedThingListingActivity extends BaseActivity implements ActivityToolbarInterface {
public static final String EXTRA_SHOW_MULTIREDDITS = "ESM";
@@ -110,7 +112,7 @@ public class SubscribedThingListingActivity extends BaseActivity implements Acti
CustomThemeWrapper mCustomThemeWrapper;
@Inject
Executor mExecutor;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private String mAccessToken;
private String mAccountName;
private boolean mInsertSuccess = false;
@@ -134,7 +136,7 @@ public class SubscribedThingListingActivity extends BaseActivity implements Acti
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -443,15 +445,15 @@ public class SubscribedThingListingActivity extends BaseActivity implements Acti
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java
index 029c4402..a12307b2 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/TrendingActivity.java
@@ -25,7 +25,6 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -47,6 +46,7 @@ import ml.docilealligator.infinityforreddit.TrendingSearch;
import ml.docilealligator.infinityforreddit.adapters.TrendingSearchRecyclerViewAdapter;
import ml.docilealligator.infinityforreddit.apis.RedditAPI;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.post.ParsePost;
import ml.docilealligator.infinityforreddit.post.Post;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java
index e3901baf..8a144d10 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewImageOrGifActivity.java
@@ -48,9 +48,6 @@ import com.github.piasy.biv.loader.glide.GlideImageLoader;
import com.github.piasy.biv.view.BigImageView;
import com.github.piasy.biv.view.GlideImageViewFactory;
import com.google.android.material.bottomappbar.BottomAppBar;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrConfig;
-import com.r0adkll.slidr.model.SlidrPosition;
import java.io.File;
import java.util.concurrent.Executor;
@@ -69,6 +66,9 @@ import ml.docilealligator.infinityforreddit.WallpaperSetter;
import ml.docilealligator.infinityforreddit.asynctasks.SaveBitmapImageToFile;
import ml.docilealligator.infinityforreddit.asynctasks.SaveGIFToFile;
import ml.docilealligator.infinityforreddit.bottomsheetfragments.SetAsWallpaperBottomSheetFragment;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrPosition;
import ml.docilealligator.infinityforreddit.font.ContentFontFamily;
import ml.docilealligator.infinityforreddit.font.ContentFontStyle;
import ml.docilealligator.infinityforreddit.font.FontFamily;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewMultiRedditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewMultiRedditDetailActivity.java
index 4b7a044d..b4de5df6 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewMultiRedditDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewMultiRedditDetailActivity.java
@@ -27,7 +27,6 @@ import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText;
-import com.r0adkll.slidr.Slidr;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -60,6 +59,7 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTimeBottomS
import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTypeBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.NavigationWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
import ml.docilealligator.infinityforreddit.events.GoBackToMainPageEvent;
import ml.docilealligator.infinityforreddit.events.RefreshMultiRedditsEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java
index e5acc1e5..68eb7a65 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewPostDetailActivity.java
@@ -40,8 +40,6 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.livefront.bridge.Bridge;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -71,6 +69,9 @@ import ml.docilealligator.infinityforreddit.apis.RedditAPI;
import ml.docilealligator.infinityforreddit.asynctasks.SwitchAccount;
import ml.docilealligator.infinityforreddit.comment.Comment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.NeedForPostListFromPostFragmentEvent;
import ml.docilealligator.infinityforreddit.events.ProvidePostListToViewPostDetailActivityEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
@@ -176,7 +177,7 @@ public class ViewPostDetailActivity extends BaseActivity implements SortTypeSele
int loadingMorePostsStatus = LoadingMorePostsStatus.NOT_LOADING;
public Map<String, String> authorIcons = new HashMap<>();
private FragmentManager fragmentManager;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private SectionsPagerAdapter sectionsPagerAdapter;
private String mAccessToken;
private String mAccountName;
@@ -237,7 +238,7 @@ public class ViewPostDetailActivity extends BaseActivity implements SortTypeSele
boolean swipeBetweenPosts = mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_BETWEEN_POSTS, false);
if (!swipeBetweenPosts) {
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
viewPager2.setUserInputEnabled(false);
}
@@ -862,15 +863,15 @@ public class ViewPostDetailActivity extends BaseActivity implements SortTypeSele
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java
index 8caebf33..d8569d9c 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewSubredditDetailActivity.java
@@ -1,6 +1,5 @@
package ml.docilealligator.infinityforreddit.activities;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.ColorStateList;
@@ -19,7 +18,6 @@ import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -47,8 +45,6 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.android.material.textfield.TextInputEditText;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -95,6 +91,8 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.SortTypeBottomS
import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.NavigationWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.GoBackToMainPageEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
@@ -226,7 +224,7 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp
private int unsubscribedColor;
private int subscribedColor;
private int fabOption;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private MaterialAlertDialogBuilder nsfwWarningBuilder;
@Override
@@ -252,7 +250,7 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -1538,15 +1536,15 @@ public class ViewSubredditDetailActivity extends BaseActivity implements SortTyp
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java
index 656a4885..2474a5fa 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/ViewUserDetailActivity.java
@@ -1,6 +1,5 @@
package ml.docilealligator.infinityforreddit.activities;
-import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.ColorStateList;
@@ -21,7 +20,6 @@ import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -49,8 +47,6 @@ import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import com.google.android.material.textfield.TextInputEditText;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -98,6 +94,9 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSh
import ml.docilealligator.infinityforreddit.bottomsheetfragments.UserThingSortTypeBottomSheetFragment;
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.NavigationWrapper;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.GoBackToMainPageEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
@@ -227,7 +226,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele
private boolean lockBottomAppBar;
private String mMessageFullname;
private String mNewAccountName;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
//private MaterialAlertDialogBuilder nsfwWarningBuilder;
@Override
@@ -255,7 +254,7 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele
applyCustomTheme();
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
username = getIntent().getStringExtra(EXTRA_USER_NAME_KEY);
@@ -1766,15 +1765,15 @@ public class ViewUserDetailActivity extends BaseActivity implements SortTypeSele
@Override
public void lockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipeRightToGoBack() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java
index 09dcd5b6..a4231c83 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/WikiActivity.java
@@ -24,8 +24,6 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
-import com.r0adkll.slidr.Slidr;
-import com.r0adkll.slidr.model.SlidrInterface;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -52,6 +50,8 @@ import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.LinearLayoutManagerBugFixed;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager;
+import ml.docilealligator.infinityforreddit.customviews.slidr.Slidr;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
import ml.docilealligator.infinityforreddit.utils.JSONUtils;
@@ -95,7 +95,7 @@ public class WikiActivity extends BaseActivity {
SharedPreferences mSharedPreferences;
@Inject
CustomThemeWrapper mCustomThemeWrapper;
- private SlidrInterface mSlidrInterface;
+ private SliderPanel mSliderPanel;
private String wikiMarkdown;
private Markwon markwon;
private MarkwonAdapter markwonAdapter;
@@ -119,7 +119,7 @@ public class WikiActivity extends BaseActivity {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (mSharedPreferences.getBoolean(SharedPreferencesUtils.SWIPE_RIGHT_TO_GO_BACK, true)) {
- mSlidrInterface = Slidr.attach(this);
+ mSliderPanel = Slidr.attach(this);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@@ -181,15 +181,15 @@ public class WikiActivity extends BaseActivity {
LinearLayoutManagerBugFixed linearLayoutManager = new SwipeLockLinearLayoutManager(this, new SwipeLockInterface() {
@Override
public void lockSwipe() {
- if (mSlidrInterface != null) {
- mSlidrInterface.lock();
+ if (mSliderPanel != null) {
+ mSliderPanel.lock();
}
}
@Override
public void unlockSwipe() {
- if (mSlidrInterface != null) {
- mSlidrInterface.unlock();
+ if (mSliderPanel != null) {
+ mSliderPanel.unlock();
}
}
});
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java
index ff68883c..af46b80e 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/adapters/RulesRecyclerViewAdapter.java
@@ -12,8 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
-import com.r0adkll.slidr.model.SlidrInterface;
-
import java.util.ArrayList;
import butterknife.BindView;
@@ -33,21 +31,22 @@ import ml.docilealligator.infinityforreddit.bottomsheetfragments.UrlMenuBottomSh
import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockInterface;
import ml.docilealligator.infinityforreddit.customviews.SwipeLockLinearLayoutManager;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
import ml.docilealligator.infinityforreddit.markdown.MarkdownUtils;
public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecyclerViewAdapter.RuleViewHolder> {
private BaseActivity activity;
private Markwon markwon;
@Nullable
- private final SlidrInterface slidrInterface;
+ private final SliderPanel sliderPanel;
private ArrayList<Rule> rules;
private int mPrimaryTextColor;
public RulesRecyclerViewAdapter(@NonNull BaseActivity activity,
@NonNull CustomThemeWrapper customThemeWrapper,
- @Nullable SlidrInterface slidrInterface) {
+ @Nullable SliderPanel sliderPanel) {
this.activity = activity;
- this.slidrInterface = slidrInterface;
+ this.sliderPanel = sliderPanel;
mPrimaryTextColor = customThemeWrapper.getPrimaryTextColor();
int spoilerBackgroundColor = mPrimaryTextColor | 0xFF000000;
MarkwonPlugin miscPlugin = new AbstractMarkwonPlugin() {
@@ -142,15 +141,15 @@ public class RulesRecyclerViewAdapter extends RecyclerView.Adapter<RulesRecycler
new SwipeLockInterface() {
@Override
public void lockSwipe() {
- if (slidrInterface != null) {
- slidrInterface.lock();
+ if (sliderPanel != null) {
+ sliderPanel.lock();
}
}
@Override
public void unlockSwipe() {
- if (slidrInterface != null) {
- slidrInterface.unlock();
+ if (sliderPanel != null) {
+ sliderPanel.unlock();
}
}
});
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ColorPanelSlideListener.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ColorPanelSlideListener.java
new file mode 100644
index 00000000..549486e9
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ColorPanelSlideListener.java
@@ -0,0 +1,68 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr;
+
+import android.animation.ArgbEvaluator;
+import android.app.Activity;
+import android.os.Build;
+
+import androidx.annotation.ColorInt;
+
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
+
+
+class ColorPanelSlideListener implements SliderPanel.OnPanelSlideListener {
+
+ private final Activity activity;
+ private final int primaryColor;
+ private final int secondaryColor;
+ private final ArgbEvaluator evaluator = new ArgbEvaluator();
+
+
+ ColorPanelSlideListener(Activity activity, @ColorInt int primaryColor, @ColorInt int secondaryColor) {
+ this.activity = activity;
+ this.primaryColor = primaryColor;
+ this.secondaryColor = secondaryColor;
+ }
+
+
+ @Override
+ public void onStateChanged(int state) {
+ // Unused.
+ }
+
+
+ @Override
+ public void onClosed() {
+ activity.finish();
+ activity.overridePendingTransition(0, 0);
+ }
+
+
+ @Override
+ public void onOpened() {
+ // Unused.
+ }
+
+
+ @Override
+ public void onSlideChange(float percent) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && areColorsValid()){
+ int newColor = (int) evaluator.evaluate(percent, getPrimaryColor(), getSecondaryColor());
+ activity.getWindow().setStatusBarColor(newColor);
+ }
+ }
+
+
+ protected int getPrimaryColor() {
+ return primaryColor;
+ }
+
+
+ protected int getSecondaryColor() {
+ return secondaryColor;
+ }
+
+
+ protected boolean areColorsValid() {
+ return getPrimaryColor() != -1 && getSecondaryColor() != -1;
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ConfigPanelSlideListener.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ConfigPanelSlideListener.java
new file mode 100644
index 00000000..768e6f7f
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/ConfigPanelSlideListener.java
@@ -0,0 +1,68 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr;
+
+
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
+
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig;
+
+
+class ConfigPanelSlideListener extends ColorPanelSlideListener {
+
+ private final SlidrConfig config;
+
+
+ ConfigPanelSlideListener(@NonNull Activity activity, @NonNull SlidrConfig config) {
+ super(activity, -1, -1);
+ this.config = config;
+ }
+
+
+ @Override
+ public void onStateChanged(int state) {
+ if(config.getListener() != null){
+ config.getListener().onSlideStateChanged(state);
+ }
+ }
+
+
+ @Override
+ public void onClosed() {
+ if(config.getListener() != null){
+ if(config.getListener().onSlideClosed()) {
+ return;
+ }
+ }
+ super.onClosed();
+ }
+
+
+ @Override
+ public void onOpened() {
+ if(config.getListener() != null){
+ config.getListener().onSlideOpened();
+ }
+ }
+
+
+ @Override
+ public void onSlideChange(float percent) {
+ super.onSlideChange(percent);
+ if(config.getListener() != null){
+ config.getListener().onSlideChange(percent);
+ }
+ }
+
+
+ @Override
+ protected int getPrimaryColor() {
+ return config.getPrimaryColor();
+ }
+
+
+ @Override
+ protected int getSecondaryColor() {
+ return config.getSecondaryColor();
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/FragmentPanelSlideListener.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/FragmentPanelSlideListener.java
new file mode 100644
index 00000000..0d52a0f6
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/FragmentPanelSlideListener.java
@@ -0,0 +1,67 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr;
+
+
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.FragmentActivity;
+
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
+
+
+class FragmentPanelSlideListener implements SliderPanel.OnPanelSlideListener {
+
+ private final View view;
+ private final SlidrConfig config;
+
+
+ FragmentPanelSlideListener(@NonNull View view, @NonNull SlidrConfig config) {
+ this.view = view;
+ this.config = config;
+ }
+
+
+ @Override
+ public void onStateChanged(int state) {
+ if (config.getListener() != null) {
+ config.getListener().onSlideStateChanged(state);
+ }
+ }
+
+
+ @Override
+ public void onClosed() {
+ if (config.getListener() != null) {
+ if(config.getListener().onSlideClosed()) {
+ return;
+ }
+ }
+
+ // Ensure that we are attached to a FragmentActivity
+ if (view.getContext() instanceof FragmentActivity) {
+ final FragmentActivity activity = (FragmentActivity) view.getContext();
+ if (activity.getSupportFragmentManager().getBackStackEntryCount() == 0) {
+ activity.finish();
+ activity.overridePendingTransition(0, 0);
+ } else {
+ activity.getSupportFragmentManager().popBackStack();
+ }
+ }
+ }
+
+ @Override
+ public void onOpened() {
+ if (config.getListener() != null) {
+ config.getListener().onSlideOpened();
+ }
+ }
+
+
+ @Override
+ public void onSlideChange(float percent) {
+ if (config.getListener() != null) {
+ config.getListener().onSlideChange(percent);
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/Slidr.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/Slidr.java
new file mode 100644
index 00000000..d9c8fe85
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/Slidr.java
@@ -0,0 +1,133 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr;
+
+
+import android.app.Activity;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+
+import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface;
+import ml.docilealligator.infinityforreddit.customviews.slidr.widget.SliderPanel;
+
+/**
+ * This attacher class is used to attach the sliding mechanism to any {@link android.app.Activity}
+ * that lets the user slide (or swipe) the activity away as a form of back or up action. The action
+ * causes {@link android.app.Activity#finish()} to be called.
+ */
+public final class Slidr {
+
+ /**
+ * Attach a slideable mechanism to an activity that adds the slide to dismiss functionality
+ *
+ * @param activity the activity to attach the slider to
+ * @return a {@link ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface} that allows
+ * the user to lock/unlock the sliding mechanism for whatever purpose.
+ */
+ @NonNull
+ public static SliderPanel attach(@NonNull Activity activity) {
+ return attach(activity, -1, -1);
+ }
+
+
+ /**
+ * Attach a slideable mechanism to an activity that adds the slide to dismiss functionality
+ * and allows for the statusbar to transition between colors
+ *
+ * @param activity the activity to attach the slider to
+ * @param statusBarColor1 the primaryDark status bar color of the interface that this will slide back to
+ * @param statusBarColor2 the primaryDark status bar color of the activity this is attaching to that will transition
+ * back to the statusBarColor1 color
+ * @return a {@link ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface} that allows
+ * the user to lock/unlock the sliding mechanism for whatever purpose.
+ */
+ @NonNull
+ public static SliderPanel attach(@NonNull Activity activity, @ColorInt int statusBarColor1,
+ @ColorInt int statusBarColor2) {
+
+ // Setup the slider panel and attach it to the decor
+ final SliderPanel panel = attachSliderPanel(activity, null);
+
+ // Set the panel slide listener for when it becomes closed or opened
+ panel.setOnPanelSlideListener(new ColorPanelSlideListener(activity, statusBarColor1, statusBarColor2));
+
+ // Return the lock interface
+ return panel;
+ }
+
+
+ /**
+ * Attach a slider mechanism to an activity based on the passed {@link ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig}
+ *
+ * @param activity the activity to attach the slider to
+ * @param config the slider configuration to make
+ * @return a {@link ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface} that allows
+ * the user to lock/unlock the sliding mechanism for whatever purpose.
+ */
+ @NonNull
+ public static SlidrInterface attach(@NonNull Activity activity, @NonNull SlidrConfig config) {
+
+ // Setup the slider panel and attach it to the decor
+ final SliderPanel panel = attachSliderPanel(activity, config);
+
+ // Set the panel slide listener for when it becomes closed or opened
+ panel.setOnPanelSlideListener(new ConfigPanelSlideListener(activity, config));
+
+ // Return the lock interface
+ return panel.getDefaultInterface();
+ }
+
+
+ /**
+ * Attach a new {@link SliderPanel} to the root of the activity's content
+ */
+ @NonNull
+ private static SliderPanel attachSliderPanel(@NonNull Activity activity, @NonNull SlidrConfig config) {
+ // Hijack the decorview
+ ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
+ View oldScreen = decorView.getChildAt(0);
+ decorView.removeViewAt(0);
+
+ // Setup the slider panel and attach it to the decor
+ SliderPanel panel = new SliderPanel(activity, oldScreen, config);
+ panel.setId(R.id.slidable_panel);
+ oldScreen.setId(R.id.slidable_content);
+ panel.addView(oldScreen);
+ decorView.addView(panel, 0);
+ return panel;
+ }
+
+
+ /**
+ * Attach a slider mechanism to a fragment view replacing an internal view
+ *
+ * @param oldScreen the view within a fragment to replace
+ * @param config the slider configuration to attach with
+ * @return a {@link ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface} that allows
+ * the user to lock/unlock the sliding mechanism for whatever purpose.
+ */
+ @NonNull
+ public static SlidrInterface replace(@NonNull final View oldScreen, @NonNull final SlidrConfig config) {
+ ViewGroup parent = (ViewGroup) oldScreen.getParent();
+ ViewGroup.LayoutParams params = oldScreen.getLayoutParams();
+ parent.removeView(oldScreen);
+
+ // Setup the slider panel and attach it
+ final SliderPanel panel = new SliderPanel(oldScreen.getContext(), oldScreen, config);
+ panel.setId(R.id.slidable_panel);
+ oldScreen.setId(R.id.slidable_content);
+
+ panel.addView(oldScreen);
+ parent.addView(panel, 0, params);
+
+ // Set the panel slide listener for when it becomes closed or opened
+ panel.setOnPanelSlideListener(new FragmentPanelSlideListener(oldScreen, config));
+
+ // Return the lock interface
+ return panel.getDefaultInterface();
+ }
+
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrConfig.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrConfig.java
new file mode 100644
index 00000000..39c5bdcc
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrConfig.java
@@ -0,0 +1,318 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.model;
+
+
+import android.graphics.Color;
+import androidx.annotation.ColorInt;
+import androidx.annotation.FloatRange;
+import androidx.customview.widget.ViewDragHelper;
+
+
+/**
+ * This class contains the configuration information for all the options available in
+ * this library
+ */
+public class SlidrConfig {
+
+ private int colorPrimary = -1;
+ private int colorSecondary = -1;
+ private float touchSize = -1f;
+ private float sensitivity = 1f;
+ private int scrimColor = Color.BLACK;
+ private float scrimStartAlpha = 0.8f;
+ private float scrimEndAlpha = 0f;
+ private float velocityThreshold = 5f;
+ private float distanceThreshold = 0.25f;
+ private boolean edgeOnly = false;
+ private float edgeSize = 0.18f;
+
+ private SlidrPosition position = SlidrPosition.LEFT;
+ private SlidrListener listener;
+
+
+ private SlidrConfig() {
+ // Unused.
+ }
+
+
+ /***********************************************************************************************
+ *
+ * Getters
+ *
+ */
+
+ /**
+ * Get the primary color that the slider will interpolate. That is this color is the color
+ * of the status bar of the Activity you are returning to
+ *
+ * @return the primary status bar color
+ */
+ public int getPrimaryColor(){
+ return colorPrimary;
+ }
+
+
+ /**
+ * Get the secondary color that the slider will interpolatel That is the color of the Activity
+ * that you are making slidable
+ *
+ * @return the secondary status bar color
+ */
+ public int getSecondaryColor(){
+ return colorSecondary;
+ }
+
+
+ /**
+ * Get the color of the background scrim
+ *
+ * @return the scrim color integer
+ */
+ @ColorInt
+ public int getScrimColor(){
+ return scrimColor;
+ }
+
+
+ /**
+ * Get teh start alpha value for when the activity is not swiped at all
+ *
+ * @return the start alpha value (0.0 to 1.0)
+ */
+ public float getScrimStartAlpha(){
+ return scrimStartAlpha;
+ }
+
+
+ /**
+ * Get the end alpha value for when the user almost swipes the activity off the screen
+ *
+ * @return the end alpha value (0.0 to 1.0)
+ */
+ public float getScrimEndAlpha(){
+ return scrimEndAlpha;
+ }
+
+
+ /**
+ * Get the position of the slidable mechanism for this configuration. This is the position on
+ * the screen that the user can swipe the activity away from
+ *
+ * @return the slider position
+ */
+ public SlidrPosition getPosition(){
+ return position;
+ }
+
+
+ /**
+ * Get the touch 'width' to be used in the gesture detection. This value should incorporate with
+ * the device's touch slop
+ *
+ * @return the touch area size
+ */
+ public float getTouchSize(){
+ return touchSize;
+ }
+
+
+ /**
+ * Get the velocity threshold at which the slide action is completed regardless of offset
+ * distance of the drag
+ *
+ * @return the velocity threshold
+ */
+ public float getVelocityThreshold(){
+ return velocityThreshold;
+ }
+
+
+ /**
+ * Get at what % of the screen is the minimum viable distance the activity has to be dragged
+ * in-order to be slinged off the screen
+ *
+ * @return the distant threshold as a percentage of the screen size (width or height)
+ */
+ public float getDistanceThreshold(){
+ return distanceThreshold;
+ }
+
+
+ /**
+ * Get the touch sensitivity set in the {@link ViewDragHelper} when
+ * creating it.
+ *
+ * @return the touch sensitivity
+ */
+ public float getSensitivity(){
+ return sensitivity;
+ }
+
+
+ /**
+ * Get the slidr listener set by the user to respond to certain events in the sliding
+ * mechanism.
+ *
+ * @return the slidr listener
+ */
+ public SlidrListener getListener(){
+ return listener;
+ }
+
+
+ /**
+ * Has the user configured slidr to only catch at the edge of the screen ?
+ *
+ * @return true if is edge capture only
+ */
+ public boolean isEdgeOnly() {
+ return edgeOnly;
+ }
+
+
+ /**
+ * Get the size of the edge field that is catchable
+ *
+ * @see #isEdgeOnly()
+ * @return the size of the edge that is grabable
+ */
+ public float getEdgeSize(float size) {
+ return edgeSize * size;
+ }
+
+
+ /***********************************************************************************************
+ *
+ * Setters
+ *
+ */
+
+
+ public void setColorPrimary(int colorPrimary) {
+ this.colorPrimary = colorPrimary;
+ }
+
+
+ public void setColorSecondary(int colorSecondary) {
+ this.colorSecondary = colorSecondary;
+ }
+
+
+ public void setTouchSize(float touchSize) {
+ this.touchSize = touchSize;
+ }
+
+
+ public void setSensitivity(float sensitivity) {
+ this.sensitivity = sensitivity;
+ }
+
+
+ public void setScrimColor(@ColorInt int scrimColor) {
+ this.scrimColor = scrimColor;
+ }
+
+
+ public void setScrimStartAlpha(float scrimStartAlpha) {
+ this.scrimStartAlpha = scrimStartAlpha;
+ }
+
+
+ public void setScrimEndAlpha(float scrimEndAlpha) {
+ this.scrimEndAlpha = scrimEndAlpha;
+ }
+
+
+ public void setVelocityThreshold(float velocityThreshold) {
+ this.velocityThreshold = velocityThreshold;
+ }
+
+
+ public void setDistanceThreshold(float distanceThreshold) {
+ this.distanceThreshold = distanceThreshold;
+ }
+
+
+ /**
+ * The Builder for this configuration class. This is the only way to create a
+ * configuration
+ */
+ public static class Builder{
+
+ private SlidrConfig config;
+
+ public Builder(){
+ config = new SlidrConfig();
+ }
+
+ public Builder primaryColor(@ColorInt int color){
+ config.colorPrimary = color;
+ return this;
+ }
+
+ public Builder secondaryColor(@ColorInt int color){
+ config.colorSecondary = color;
+ return this;
+ }
+
+ public Builder position(SlidrPosition position){
+ config.position = position;
+ return this;
+ }
+
+ public Builder touchSize(float size){
+ config.touchSize = size;
+ return this;
+ }
+
+ public Builder sensitivity(float sensitivity){
+ config.sensitivity = sensitivity;
+ return this;
+ }
+
+ public Builder scrimColor(@ColorInt int color){
+ config.scrimColor = color;
+ return this;
+ }
+
+ public Builder scrimStartAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha){
+ config.scrimStartAlpha = alpha;
+ return this;
+ }
+
+ public Builder scrimEndAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha){
+ config.scrimEndAlpha = alpha;
+ return this;
+ }
+
+ public Builder velocityThreshold(float threshold){
+ config.velocityThreshold = threshold;
+ return this;
+ }
+
+ public Builder distanceThreshold(@FloatRange(from = .1f, to = .9f) float threshold){
+ config.distanceThreshold = threshold;
+ return this;
+ }
+
+ public Builder edge(boolean flag){
+ config.edgeOnly = flag;
+ return this;
+ }
+
+ public Builder edgeSize(@FloatRange(from = 0f, to = 1f) float edgeSize){
+ config.edgeSize = edgeSize;
+ return this;
+ }
+
+ public Builder listener(SlidrListener listener){
+ config.listener = listener;
+ return this;
+ }
+
+ public SlidrConfig build(){
+ return config;
+ }
+
+ }
+
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrInterface.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrInterface.java
new file mode 100644
index 00000000..d8074d8a
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrInterface.java
@@ -0,0 +1,8 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.model;
+
+
+public interface SlidrInterface {
+
+ void lock();
+ void unlock();
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListener.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListener.java
new file mode 100644
index 00000000..627a3214
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListener.java
@@ -0,0 +1,31 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.model;
+
+import androidx.customview.widget.ViewDragHelper;
+
+/**
+ * This listener interface is for receiving events from the sliding panel such as state changes
+ * and slide progress
+ */
+public interface SlidrListener {
+
+ /**
+ * This is called when the {@link ViewDragHelper} calls it's
+ * state change callback.
+ *
+ * @see ViewDragHelper#STATE_IDLE
+ * @see ViewDragHelper#STATE_DRAGGING
+ * @see ViewDragHelper#STATE_SETTLING
+ *
+ * @param state the {@link ViewDragHelper} state
+ */
+ void onSlideStateChanged(int state);
+
+ void onSlideChange(float percent);
+
+ void onSlideOpened();
+
+ /**
+ * @return <code>true</code> than event was processed in the callback.
+ */
+ boolean onSlideClosed();
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListenerAdapter.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListenerAdapter.java
new file mode 100644
index 00000000..da5b23bf
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrListenerAdapter.java
@@ -0,0 +1,22 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.model;
+
+
+public class SlidrListenerAdapter implements SlidrListener {
+
+ @Override
+ public void onSlideStateChanged(int state) {
+ }
+
+ @Override
+ public void onSlideChange(float percent) {
+ }
+
+ @Override
+ public void onSlideOpened() {
+ }
+
+ @Override
+ public boolean onSlideClosed() {
+ return false;
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrPosition.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrPosition.java
new file mode 100644
index 00000000..5c270601
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/model/SlidrPosition.java
@@ -0,0 +1,12 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.model;
+
+
+public enum SlidrPosition {
+
+ LEFT,
+ RIGHT,
+ TOP,
+ BOTTOM,
+ VERTICAL,
+ HORIZONTAL
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/util/ViewDragHelper.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/util/ViewDragHelper.java
new file mode 100644
index 00000000..2f4c9206
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/util/ViewDragHelper.java
@@ -0,0 +1,1404 @@
+/**
+ * Created by Gabriele Guerrisi on 24/11/2017.
+ */
+package ml.docilealligator.infinityforreddit.customviews.slidr.util;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.Interpolator;
+
+import androidx.core.view.MotionEventCompat;
+import androidx.core.view.VelocityTrackerCompat;
+import androidx.core.view.ViewCompat;
+import androidx.core.widget.ScrollerCompat;
+
+import java.util.Arrays;
+
+/**
+ * ViewDragHelper is a utility class for writing custom ViewGroups. It offers a number
+ * of useful operations and state tracking for allowing a user to drag and reposition
+ * views within their parent ViewGroup.
+ */
+public class ViewDragHelper {
+ private static final String TAG = "ViewDragHelper";
+ /**
+ * A null/invalid pointer ID.
+ */
+ public static final int INVALID_POINTER = -1;
+ /**
+ * A view is not currently being dragged or animating as a result of a fling/snap.
+ */
+ public static final int STATE_IDLE = 0;
+ /**
+ * A view is currently being dragged. The position is currently changing as a result
+ * of user input or simulated user input.
+ */
+ public static final int STATE_DRAGGING = 1;
+ /**
+ * A view is currently settling into place as a result of a fling or
+ * predefined non-interactive motion.
+ */
+ public static final int STATE_SETTLING = 2;
+ /**
+ * Edge flag indicating that the left edge should be affected.
+ */
+ public static final int EDGE_LEFT = 1 << 0;
+ /**
+ * Edge flag indicating that the right edge should be affected.
+ */
+ public static final int EDGE_RIGHT = 1 << 1;
+ /**
+ * Edge flag indicating that the top edge should be affected.
+ */
+ public static final int EDGE_TOP = 1 << 2;
+ /**
+ * Edge flag indicating that the bottom edge should be affected.
+ */
+ public static final int EDGE_BOTTOM = 1 << 3;
+ /**
+ * Edge flag set indicating all edges should be affected.
+ */
+ public static final int EDGE_ALL = EDGE_LEFT | EDGE_TOP | EDGE_RIGHT | EDGE_BOTTOM;
+ /**
+ * Indicates that a check should occur along the horizontal axis
+ */
+ public static final int DIRECTION_HORIZONTAL = 1 << 0;
+ /**
+ * Indicates that a check should occur along the vertical axis
+ */
+ public static final int DIRECTION_VERTICAL = 1 << 1;
+ /**
+ * Indicates that a check should occur along all axes
+ */
+ public static final int DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
+ private static final int EDGE_SIZE = 20; // dp
+ private static final int BASE_SETTLE_DURATION = 256; // ms
+ private static final int MAX_SETTLE_DURATION = 600; // ms
+ // Current drag state; idle, dragging or settling
+ private int mDragState;
+ // Distance to travel before a drag may begin
+ private int mTouchSlop;
+ // Last known position/pointer tracking
+ private int mActivePointerId = INVALID_POINTER;
+ private float[] mInitialMotionX;
+ private float[] mInitialMotionY;
+ private float[] mLastMotionX;
+ private float[] mLastMotionY;
+ private int[] mInitialEdgesTouched;
+ private int[] mEdgeDragsInProgress;
+ private int[] mEdgeDragsLocked;
+ private int mPointersDown;
+ private VelocityTracker mVelocityTracker;
+ private float mMaxVelocity;
+ private float mMinVelocity;
+ private int mEdgeSize;
+ private int mTrackingEdges;
+ private ScrollerCompat mScroller;
+ private final Callback mCallback;
+ private View mCapturedView;
+ private boolean mReleaseInProgress;
+ private final ViewGroup mParentView;
+
+ /**
+ * A Callback is used as a communication channel with the ViewDragHelper back to the
+ * parent view using it. <code>on*</code>methods are invoked on siginficant events and several
+ * accessor methods are expected to provide the ViewDragHelper with more information
+ * about the state of the parent view upon request. The callback also makes decisions
+ * governing the range and draggability of child views.
+ */
+ public static abstract class Callback {
+ /**
+ * Called when the drag state changes. See the <code>STATE_*</code> constants
+ * for more information.
+ *
+ * @param state The new drag state
+ * @see #STATE_IDLE
+ * @see #STATE_DRAGGING
+ * @see #STATE_SETTLING
+ */
+ public void onViewDragStateChanged(int state) {
+ }
+
+ /**
+ * Called when the captured view's position changes as the result of a drag or settle.
+ *
+ * @param changedView View whose position changed
+ * @param left New X coordinate of the left edge of the view
+ * @param top New Y coordinate of the top edge of the view
+ * @param dx Change in X position from the last call
+ * @param dy Change in Y position from the last call
+ */
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ }
+
+ /**
+ * Called when a child view is captured for dragging or settling. The ID of the pointer
+ * currently dragging the captured view is supplied. If activePointerId is
+ * identified as {@link #INVALID_POINTER} the capture is programmatic instead of
+ * pointer-initiated.
+ *
+ * @param capturedChild Child view that was captured
+ * @param activePointerId Pointer id tracking the child capture
+ */
+ public void onViewCaptured(View capturedChild, int activePointerId) {
+ }
+
+ /**
+ * Called when the child view is no longer being actively dragged.
+ * The fling velocity is also supplied, if relevant. The velocity values may
+ * be clamped to system minimums or maximums.
+ * <p>
+ * <p>Calling code may decide to fling or otherwise release the view to let it
+ * settle into place. It should do so using {@link #settleCapturedViewAt(int, int)}
+ * or {@link #flingCapturedView(int, int, int, int)}. If the Callback invokes
+ * one of these methods, the ViewDragHelper will enter {@link #STATE_SETTLING}
+ * and the view capture will not fully end until it comes to a complete stop.
+ * If neither of these methods is invoked before <code>onViewReleased</code> returns,
+ * the view will stop in place and the ViewDragHelper will return to
+ * {@link #STATE_IDLE}.</p>
+ *
+ * @param releasedChild The captured child view now being released
+ * @param xvel X velocity of the pointer as it left the screen in pixels per second.
+ * @param yvel Y velocity of the pointer as it left the screen in pixels per second.
+ */
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ }
+
+ /**
+ * Called when one of the subscribed edges in the parent view has been touched
+ * by the user while no child view is currently captured.
+ *
+ * @param edgeFlags A combination of edge flags describing the edge(s) currently touched
+ * @param pointerId ID of the pointer touching the described edge(s)
+ * @see #EDGE_LEFT
+ * @see #EDGE_TOP
+ * @see #EDGE_RIGHT
+ * @see #EDGE_BOTTOM
+ */
+ public void onEdgeTouched(int edgeFlags, int pointerId) {
+ }
+
+ /**
+ * Called when the given edge may become locked. This can happen if an edge drag
+ * was preliminarily rejected before beginning, but after {@link #onEdgeTouched(int, int)}
+ * was called. This method should return true to lock this edge or false to leave it
+ * unlocked. The default behavior is to leave edges unlocked.
+ *
+ * @param edgeFlags A combination of edge flags describing the edge(s) locked
+ * @return true to lock the edge, false to leave it unlocked
+ */
+ public boolean onEdgeLock(int edgeFlags) {
+ return false;
+ }
+
+ /**
+ * Called when the user has started a deliberate drag away from one
+ * of the subscribed edges in the parent view while no child view is currently captured.
+ *
+ * @param edgeFlags A combination of edge flags describing the edge(s) dragged
+ * @param pointerId ID of the pointer touching the described edge(s)
+ * @see #EDGE_LEFT
+ * @see #EDGE_TOP
+ * @see #EDGE_RIGHT
+ * @see #EDGE_BOTTOM
+ */
+ public void onEdgeDragStarted(int edgeFlags, int pointerId) {
+ }
+
+ /**
+ * Called to determine the Z-order of child views.
+ *
+ * @param index the ordered position to query for
+ * @return index of the view that should be ordered at position <code>index</code>
+ */
+ public int getOrderedChildIndex(int index) {
+ return index;
+ }
+
+ /**
+ * Return the magnitude of a draggable child view's horizontal range of motion in pixels.
+ * This method should return 0 for views that cannot move horizontally.
+ *
+ * @param child Child view to check
+ * @return range of horizontal motion in pixels
+ */
+ public int getViewHorizontalDragRange(View child) {
+ return 0;
+ }
+
+ /**
+ * Return the magnitude of a draggable child view's vertical range of motion in pixels.
+ * This method should return 0 for views that cannot move vertically.
+ *
+ * @param child Child view to check
+ * @return range of vertical motion in pixels
+ */
+ public int getViewVerticalDragRange(View child) {
+ return 0;
+ }
+
+ /**
+ * Called when the user's input indicates that they want to capture the given child view
+ * with the pointer indicated by pointerId. The callback should return true if the user
+ * is permitted to drag the given view with the indicated pointer.
+ * <p>
+ * <p>ViewDragHelper may call this method multiple times for the same view even if
+ * the view is already captured; this indicates that a new pointer is trying to take
+ * control of the view.</p>
+ * <p>
+ * <p>If this method returns true, a call to {@link #onViewCaptured(android.view.View, int)}
+ * will follow if the capture is successful.</p>
+ *
+ * @param child Child the user is attempting to capture
+ * @param pointerId ID of the pointer attempting the capture
+ * @return true if capture should be allowed, false otherwise
+ */
+ public abstract boolean tryCaptureView(View child, int pointerId);
+
+ /**
+ * Restrict the motion of the dragged child view along the horizontal axis.
+ * The default implementation does not allow horizontal motion; the extending
+ * class must override this method and provide the desired clamping.
+ *
+ * @param child Child view being dragged
+ * @param left Attempted motion along the X axis
+ * @param dx Proposed change in position for left
+ * @return The new clamped position for left
+ */
+ public int clampViewPositionHorizontal(View child, int left, int dx) {
+ return 0;
+ }
+
+ /**
+ * Restrict the motion of the dragged child view along the vertical axis.
+ * The default implementation does not allow vertical motion; the extending
+ * class must override this method and provide the desired clamping.
+ *
+ * @param child Child view being dragged
+ * @param top Attempted motion along the Y axis
+ * @param dy Proposed change in position for top
+ * @return The new clamped position for top
+ */
+ public int clampViewPositionVertical(View child, int top, int dy) {
+ return 0;
+ }
+ }
+
+ /**
+ * Interpolator defining the animation curve for mScroller
+ */
+ private static final Interpolator sInterpolator = new Interpolator() {
+ public float getInterpolation(float t) {
+ t -= 1.0f;
+ return t * t * t * t * t + 1.0f;
+ }
+ };
+ private final Runnable mSetIdleRunnable = new Runnable() {
+ public void run() {
+ setDragState(STATE_IDLE);
+ }
+ };
+
+ /**
+ * Factory method to create a new ViewDragHelper.
+ *
+ * @param forParent Parent view to monitor
+ * @param cb Callback to provide information and receive events
+ * @return a new ViewDragHelper instance
+ */
+ public static ViewDragHelper create(ViewGroup forParent, Callback cb) {
+ return new ViewDragHelper(forParent.getContext(), forParent, cb);
+ }
+
+ /**
+ * Factory method to create a new ViewDragHelper.
+ *
+ * @param forParent Parent view to monitor
+ * @param sensitivity Multiplier for how sensitive the helper should be about detecting
+ * the start of a drag. Larger values are more sensitive. 1.0f is normal.
+ * @param cb Callback to provide information and receive events
+ * @return a new ViewDragHelper instance
+ */
+ public static ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb) {
+ final ViewDragHelper helper = create(forParent, cb);
+ helper.mTouchSlop = (int) (helper.mTouchSlop * (1 / sensitivity));
+ return helper;
+ }
+
+ /**
+ * Apps should use ViewDragHelper.create() to get a new instance.
+ * This will allow VDH to use internal compatibility implementations for different
+ * platform versions.
+ *
+ * @param context Context to initialize config-dependent params from
+ * @param forParent Parent view to monitor
+ */
+ private ViewDragHelper(Context context, ViewGroup forParent, Callback cb) {
+ if (forParent == null) {
+ throw new IllegalArgumentException("Parent view may not be null");
+ }
+ if (cb == null) {
+ throw new IllegalArgumentException("Callback may not be null");
+ }
+ mParentView = forParent;
+ mCallback = cb;
+ final ViewConfiguration vc = ViewConfiguration.get(context);
+ final float density = context.getResources().getDisplayMetrics().density;
+ mEdgeSize = (int) (EDGE_SIZE * density + 0.5f);
+ mTouchSlop = vc.getScaledTouchSlop();
+ mMaxVelocity = vc.getScaledMaximumFlingVelocity();
+ mMinVelocity = vc.getScaledMinimumFlingVelocity();
+ mScroller = ScrollerCompat.create(context, sInterpolator);
+ }
+
+ /**
+ * Set the minimum velocity that will be detected as having a magnitude greater than zero
+ * in pixels per second. Callback methods accepting a velocity will be clamped appropriately.
+ *
+ * @param minVel Minimum velocity to detect
+ */
+ public void setMinVelocity(float minVel) {
+ mMinVelocity = minVel;
+ }
+
+ /**
+ * Return the currently configured minimum velocity. Any flings with a magnitude less
+ * than this value in pixels per second. Callback methods accepting a velocity will receive
+ * zero as a velocity value if the real detected velocity was below this threshold.
+ *
+ * @return the minimum velocity that will be detected
+ */
+ public float getMinVelocity() {
+ return mMinVelocity;
+ }
+
+ /**
+ * Retrieve the current drag state of this helper. This will return one of
+ * {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
+ *
+ * @return The current drag state
+ */
+ public int getViewDragState() {
+ return mDragState;
+ }
+
+ /**
+ * Enable edge tracking for the selected edges of the parent view.
+ * The callback's {@link Callback#onEdgeTouched(int, int)} and
+ * {@link Callback#onEdgeDragStarted(int, int)} methods will only be invoked
+ * for edges for which edge tracking has been enabled.
+ *
+ * @param edgeFlags Combination of edge flags describing the edges to watch
+ * @see #EDGE_LEFT
+ * @see #EDGE_TOP
+ * @see #EDGE_RIGHT
+ * @see #EDGE_BOTTOM
+ */
+ public void setEdgeTrackingEnabled(int edgeFlags) {
+ mTrackingEdges = edgeFlags;
+ }
+
+ /**
+ * Return the size of an edge. This is the range in pixels along the edges of this view
+ * that will actively detect edge touches or drags if edge tracking is enabled.
+ *
+ * @return The size of an edge in pixels
+ * @see #setEdgeTrackingEnabled(int)
+ */
+ public int getEdgeSize() {
+ return mEdgeSize;
+ }
+
+ /**
+ * Capture a specific child view for dragging within the parent. The callback will be notified
+ * but {@link Callback#tryCaptureView(android.view.View, int)} will not be asked permission to
+ * capture this view.
+ *
+ * @param childView Child view to capture
+ * @param activePointerId ID of the pointer that is dragging the captured child view
+ */
+ public void captureChildView(View childView, int activePointerId) {
+ if (childView.getParent() != mParentView) {
+ throw new IllegalArgumentException("captureChildView: parameter must be a descendant " +
+ "of the ViewDragHelper's tracked parent view (" + mParentView + ")");
+ }
+ mCapturedView = childView;
+ mActivePointerId = activePointerId;
+ mCallback.onViewCaptured(childView, activePointerId);
+ setDragState(STATE_DRAGGING);
+ }
+
+ /**
+ * @return The currently captured view, or null if no view has been captured.
+ */
+ public View getCapturedView() {
+ return mCapturedView;
+ }
+
+ /**
+ * @return The ID of the pointer currently dragging the captured view,
+ * or {@link #INVALID_POINTER}.
+ */
+ public int getActivePointerId() {
+ return mActivePointerId;
+ }
+
+ /**
+ * @return The minimum distance in pixels that the user must travel to initiate a drag
+ */
+ public int getTouchSlop() {
+ return mTouchSlop;
+ }
+
+ /**
+ * The result of a call to this method is equivalent to
+ * {@link #processTouchEvent(android.view.MotionEvent)} receiving an ACTION_CANCEL event.
+ */
+ public void cancel() {
+ mActivePointerId = INVALID_POINTER;
+ clearMotionHistory();
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
+ /**
+ * {@link #cancel()}, but also abort all motion in progress and snap to the end of any
+ * animation.
+ */
+ public void abort() {
+ cancel();
+ if (mDragState == STATE_SETTLING) {
+ final int oldX = mScroller.getCurrX();
+ final int oldY = mScroller.getCurrY();
+ mScroller.abortAnimation();
+ final int newX = mScroller.getCurrX();
+ final int newY = mScroller.getCurrY();
+ mCallback.onViewPositionChanged(mCapturedView, newX, newY, newX - oldX, newY - oldY);
+ }
+ setDragState(STATE_IDLE);
+ }
+
+ /**
+ * Animate the view <code>child</code> to the given (left, top) position.
+ * If this method returns true, the caller should invoke {@link #continueSettling(boolean)}
+ * on each subsequent frame to continue the motion until it returns false. If this method
+ * returns false there is no further work to do to complete the movement.
+ * <p>
+ * <p>This operation does not count as a capture event, though {@link #getCapturedView()}
+ * will still report the sliding view while the slide is in progress.</p>
+ *
+ * @param child Child view to capture and animate
+ * @param finalLeft Final left position of child
+ * @param finalTop Final top position of child
+ * @return true if animation should continue through {@link #continueSettling(boolean)} calls
+ */
+ public boolean smoothSlideViewTo(View child, int finalLeft, int finalTop) {
+ mCapturedView = child;
+ mActivePointerId = INVALID_POINTER;
+ boolean continueSliding = forceSettleCapturedViewAt(finalLeft, finalTop, 0, 0);
+ if (!continueSliding && mDragState == STATE_IDLE && mCapturedView != null) {
+ // If we're in an IDLE state to begin with and aren't moving anywhere, we
+ // end up having a non-null capturedView with an IDLE dragState
+ mCapturedView = null;
+ }
+ return continueSliding;
+ }
+
+ /**
+ * Settle the captured view at the given (left, top) position.
+ * The appropriate velocity from prior motion will be taken into account.
+ * If this method returns true, the caller should invoke {@link #continueSettling(boolean)}
+ * on each subsequent frame to continue the motion until it returns false. If this method
+ * returns false there is no further work to do to complete the movement.
+ *
+ * @param finalLeft Settled left edge position for the captured view
+ * @param finalTop Settled top edge position for the captured view
+ * @return true if animation should continue through {@link #continueSettling(boolean)} calls
+ */
+ public boolean settleCapturedViewAt(int finalLeft, int finalTop) {
+ if (!mReleaseInProgress) {
+ throw new IllegalStateException("Cannot settleCapturedViewAt outside of a call to " +
+ "Callback#onViewReleased");
+ }
+ return forceSettleCapturedViewAt(finalLeft, finalTop,
+ (int) VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId),
+ (int) VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId));
+ }
+
+ /**
+ * Settle the captured view at the given (left, top) position.
+ *
+ * @param finalLeft Target left position for the captured view
+ * @param finalTop Target top position for the captured view
+ * @param xvel Horizontal velocity
+ * @param yvel Vertical velocity
+ * @return true if animation should continue through {@link #continueSettling(boolean)} calls
+ */
+ private boolean forceSettleCapturedViewAt(int finalLeft, int finalTop, int xvel, int yvel) {
+ final int startLeft = mCapturedView.getLeft();
+ final int startTop = mCapturedView.getTop();
+ final int dx = finalLeft - startLeft;
+ final int dy = finalTop - startTop;
+ if (dx == 0 && dy == 0) {
+ // Nothing to do. Send callbacks, be done.
+ mScroller.abortAnimation();
+ setDragState(STATE_IDLE);
+ return false;
+ }
+ final int duration = computeSettleDuration(mCapturedView, dx, dy, xvel, yvel);
+ mScroller.startScroll(startLeft, startTop, dx, dy, duration);
+ setDragState(STATE_SETTLING);
+ return true;
+ }
+
+ private int computeSettleDuration(View child, int dx, int dy, int xvel, int yvel) {
+ xvel = clampMag(xvel, (int) mMinVelocity, (int) mMaxVelocity);
+ yvel = clampMag(yvel, (int) mMinVelocity, (int) mMaxVelocity);
+ final int absDx = Math.abs(dx);
+ final int absDy = Math.abs(dy);
+ final int absXVel = Math.abs(xvel);
+ final int absYVel = Math.abs(yvel);
+ final int addedVel = absXVel + absYVel;
+ final int addedDistance = absDx + absDy;
+ final float xweight = xvel != 0 ? (float) absXVel / addedVel :
+ (float) absDx / addedDistance;
+ final float yweight = yvel != 0 ? (float) absYVel / addedVel :
+ (float) absDy / addedDistance;
+ int xduration = computeAxisDuration(dx, xvel, mCallback.getViewHorizontalDragRange(child));
+ int yduration = computeAxisDuration(dy, yvel, mCallback.getViewVerticalDragRange(child));
+ return (int) (xduration * xweight + yduration * yweight);
+ }
+
+ private int computeAxisDuration(int delta, int velocity, int motionRange) {
+ if (delta == 0) {
+ return 0;
+ }
+ final int width = mParentView.getWidth();
+ final int halfWidth = width / 2;
+ final float distanceRatio = Math.min(1f, (float) Math.abs(delta) / width);
+ final float distance = halfWidth + halfWidth *
+ distanceInfluenceForSnapDuration(distanceRatio);
+ int duration;
+ velocity = Math.abs(velocity);
+ if (velocity > 0) {
+ duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
+ } else {
+ final float range = (float) Math.abs(delta) / motionRange;
+ duration = (int) ((range + 1) * BASE_SETTLE_DURATION);
+ }
+ return Math.min(duration, MAX_SETTLE_DURATION);
+ }
+
+ /**
+ * Clamp the magnitude of value for absMin and absMax.
+ * If the value is below the minimum, it will be clamped to zero.
+ * If the value is above the maximum, it will be clamped to the maximum.
+ *
+ * @param value Value to clamp
+ * @param absMin Absolute value of the minimum significant value to return
+ * @param absMax Absolute value of the maximum value to return
+ * @return The clamped value with the same sign as <code>value</code>
+ */
+ private int clampMag(int value, int absMin, int absMax) {
+ final int absValue = Math.abs(value);
+ if (absValue < absMin) return 0;
+ if (absValue > absMax) return value > 0 ? absMax : -absMax;
+ return value;
+ }
+
+ /**
+ * Clamp the magnitude of value for absMin and absMax.
+ * If the value is below the minimum, it will be clamped to zero.
+ * If the value is above the maximum, it will be clamped to the maximum.
+ *
+ * @param value Value to clamp
+ * @param absMin Absolute value of the minimum significant value to return
+ * @param absMax Absolute value of the maximum value to return
+ * @return The clamped value with the same sign as <code>value</code>
+ */
+ private float clampMag(float value, float absMin, float absMax) {
+ final float absValue = Math.abs(value);
+ if (absValue < absMin) return 0;
+ if (absValue > absMax) return value > 0 ? absMax : -absMax;
+ return value;
+ }
+
+ private float distanceInfluenceForSnapDuration(float f) {
+ f -= 0.5f; // center the values about 0.
+ f *= 0.3f * Math.PI / 2.0f;
+ return (float) Math.sin(f);
+ }
+
+ /**
+ * Settle the captured view based on standard free-moving fling behavior.
+ * The caller should invoke {@link #continueSettling(boolean)} on each subsequent frame
+ * to continue the motion until it returns false.
+ *
+ * @param minLeft Minimum X position for the view's left edge
+ * @param minTop Minimum Y position for the view's top edge
+ * @param maxLeft Maximum X position for the view's left edge
+ * @param maxTop Maximum Y position for the view's top edge
+ */
+ public void flingCapturedView(int minLeft, int minTop, int maxLeft, int maxTop) {
+ if (!mReleaseInProgress) {
+ throw new IllegalStateException("Cannot flingCapturedView outside of a call to " +
+ "Callback#onViewReleased");
+ }
+ mScroller.fling(mCapturedView.getLeft(), mCapturedView.getTop(),
+ (int) VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId),
+ (int) VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId),
+ minLeft, maxLeft, minTop, maxTop);
+ setDragState(STATE_SETTLING);
+ }
+
+ /**
+ * Move the captured settling view by the appropriate amount for the current time.
+ * If <code>continueSettling</code> returns true, the caller should call it again
+ * on the next frame to continue.
+ *
+ * @param deferCallbacks true if state callbacks should be deferred via posted message.
+ * Set this to true if you are calling this method from
+ * {@link android.view.View#computeScroll()} or similar methods
+ * invoked as part of layout or drawing.
+ * @return true if settle is still in progress
+ */
+ public boolean continueSettling(boolean deferCallbacks) {
+ if (mDragState == STATE_SETTLING) {
+ boolean keepGoing = mScroller.computeScrollOffset();
+ final int x = mScroller.getCurrX();
+ final int y = mScroller.getCurrY();
+ final int dx = x - mCapturedView.getLeft();
+ final int dy = y - mCapturedView.getTop();
+ if (dx != 0) {
+ ViewCompat.offsetLeftAndRight(mCapturedView, dx);
+ }
+ if (dy != 0) {
+ ViewCompat.offsetTopAndBottom(mCapturedView, dy);
+ }
+ if (dx != 0 || dy != 0) {
+ mCallback.onViewPositionChanged(mCapturedView, x, y, dx, dy);
+ }
+ if (keepGoing && x == mScroller.getFinalX() && y == mScroller.getFinalY()) {
+ // Close enough. The interpolator/scroller might think we're still moving
+ // but the user sure doesn't.
+ mScroller.abortAnimation();
+ keepGoing = false;
+ }
+ if (!keepGoing) {
+ if (deferCallbacks) {
+ mParentView.post(mSetIdleRunnable);
+ } else {
+ setDragState(STATE_IDLE);
+ }
+ }
+ }
+ return mDragState == STATE_SETTLING;
+ }
+
+ /**
+ * Like all callback events this must happen on the UI thread, but release
+ * involves some extra semantics. During a release (mReleaseInProgress)
+ * is the only time it is valid to call {@link #settleCapturedViewAt(int, int)}
+ * or {@link #flingCapturedView(int, int, int, int)}.
+ */
+ private void dispatchViewReleased(float xvel, float yvel) {
+ mReleaseInProgress = true;
+ mCallback.onViewReleased(mCapturedView, xvel, yvel);
+ mReleaseInProgress = false;
+ if (mDragState == STATE_DRAGGING) {
+ // onViewReleased didn't call a method that would have changed this. Go idle.
+ setDragState(STATE_IDLE);
+ }
+ }
+
+ private void clearMotionHistory() {
+ if (mInitialMotionX == null) {
+ return;
+ }
+ Arrays.fill(mInitialMotionX, 0);
+ Arrays.fill(mInitialMotionY, 0);
+ Arrays.fill(mLastMotionX, 0);
+ Arrays.fill(mLastMotionY, 0);
+ Arrays.fill(mInitialEdgesTouched, 0);
+ Arrays.fill(mEdgeDragsInProgress, 0);
+ Arrays.fill(mEdgeDragsLocked, 0);
+ mPointersDown = 0;
+ }
+
+ private void clearMotionHistory(int pointerId) {
+ if (mInitialMotionX == null || !isPointerDown(pointerId)) {
+ return;
+ }
+ mInitialMotionX[pointerId] = 0;
+ mInitialMotionY[pointerId] = 0;
+ mLastMotionX[pointerId] = 0;
+ mLastMotionY[pointerId] = 0;
+ mInitialEdgesTouched[pointerId] = 0;
+ mEdgeDragsInProgress[pointerId] = 0;
+ mEdgeDragsLocked[pointerId] = 0;
+ mPointersDown &= ~(1 << pointerId);
+ }
+
+ private void ensureMotionHistorySizeForId(int pointerId) {
+ if (mInitialMotionX == null || mInitialMotionX.length <= pointerId) {
+ float[] imx = new float[pointerId + 1];
+ float[] imy = new float[pointerId + 1];
+ float[] lmx = new float[pointerId + 1];
+ float[] lmy = new float[pointerId + 1];
+ int[] iit = new int[pointerId + 1];
+ int[] edip = new int[pointerId + 1];
+ int[] edl = new int[pointerId + 1];
+ if (mInitialMotionX != null) {
+ System.arraycopy(mInitialMotionX, 0, imx, 0, mInitialMotionX.length);
+ System.arraycopy(mInitialMotionY, 0, imy, 0, mInitialMotionY.length);
+ System.arraycopy(mLastMotionX, 0, lmx, 0, mLastMotionX.length);
+ System.arraycopy(mLastMotionY, 0, lmy, 0, mLastMotionY.length);
+ System.arraycopy(mInitialEdgesTouched, 0, iit, 0, mInitialEdgesTouched.length);
+ System.arraycopy(mEdgeDragsInProgress, 0, edip, 0, mEdgeDragsInProgress.length);
+ System.arraycopy(mEdgeDragsLocked, 0, edl, 0, mEdgeDragsLocked.length);
+ }
+ mInitialMotionX = imx;
+ mInitialMotionY = imy;
+ mLastMotionX = lmx;
+ mLastMotionY = lmy;
+ mInitialEdgesTouched = iit;
+ mEdgeDragsInProgress = edip;
+ mEdgeDragsLocked = edl;
+ }
+ }
+
+ private void saveInitialMotion(float x, float y, int pointerId) {
+ ensureMotionHistorySizeForId(pointerId);
+ mInitialMotionX[pointerId] = mLastMotionX[pointerId] = x;
+ mInitialMotionY[pointerId] = mLastMotionY[pointerId] = y;
+ mInitialEdgesTouched[pointerId] = getEdgesTouched((int) x, (int) y);
+ mPointersDown |= 1 << pointerId;
+ }
+
+ private void saveLastMotion(MotionEvent ev) {
+ final int pointerCount = MotionEventCompat.getPointerCount(ev);
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = MotionEventCompat.getPointerId(ev, i);
+ // If pointer is invalid then skip saving on ACTION_MOVE.
+ if (!isValidPointerForActionMove(pointerId)) {
+ continue;
+ }
+ final float x = MotionEventCompat.getX(ev, i);
+ final float y = MotionEventCompat.getY(ev, i);
+ mLastMotionX[pointerId] = x;
+ mLastMotionY[pointerId] = y;
+ }
+ }
+
+ /**
+ * Check if the given pointer ID represents a pointer that is currently down (to the best
+ * of the ViewDragHelper's knowledge).
+ * <p>
+ * <p>The state used to report this information is populated by the methods
+ * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
+ * {@link #processTouchEvent(android.view.MotionEvent)}. If one of these methods has not
+ * been called for all relevant MotionEvents to track, the information reported
+ * by this method may be stale or incorrect.</p>
+ *
+ * @param pointerId pointer ID to check; corresponds to IDs provided by MotionEvent
+ * @return true if the pointer with the given ID is still down
+ */
+ public boolean isPointerDown(int pointerId) {
+ return (mPointersDown & 1 << pointerId) != 0;
+ }
+
+ void setDragState(int state) {
+ mParentView.removeCallbacks(mSetIdleRunnable);
+ if (mDragState != state) {
+ mDragState = state;
+ mCallback.onViewDragStateChanged(state);
+ if (mDragState == STATE_IDLE) {
+ mCapturedView = null;
+ }
+ }
+ }
+
+ /**
+ * Attempt to capture the view with the given pointer ID. The callback will be involved.
+ * This will put us into the "dragging" state. If we've already captured this view with
+ * this pointer this method will immediately return true without consulting the callback.
+ *
+ * @param toCapture View to capture
+ * @param pointerId Pointer to capture with
+ * @return true if capture was successful
+ */
+ boolean tryCaptureViewForDrag(View toCapture, int pointerId) {
+ if (toCapture == mCapturedView && mActivePointerId == pointerId) {
+ // Already done!
+ return true;
+ }
+ if (toCapture != null && mCallback.tryCaptureView(toCapture, pointerId)) {
+ mActivePointerId = pointerId;
+ captureChildView(toCapture, pointerId);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Tests scrollability within child views of v given a delta of dx.
+ *
+ * @param v View to test for horizontal scrollability
+ * @param checkV Whether the view v passed should itself be checked for scrollability (true),
+ * or just its children (false).
+ * @param dx Delta scrolled in pixels along the X axis
+ * @param dy Delta scrolled in pixels along the Y axis
+ * @param x X coordinate of the active touch point
+ * @param y Y coordinate of the active touch point
+ * @return true if child views of v can be scrolled by delta of dx.
+ */
+ protected boolean canScroll(View v, boolean checkV, int dx, int dy, int x, int y) {
+ if (v instanceof ViewGroup) {
+ final ViewGroup group = (ViewGroup) v;
+ final int scrollX = v.getScrollX();
+ final int scrollY = v.getScrollY();
+ final int count = group.getChildCount();
+ // Count backwards - let topmost views consume scroll distance first.
+ for (int i = count - 1; i >= 0; i--) {
+ // TODO: Add versioned support here for transformed views.
+ // This will not work for transformed views in Honeycomb+
+ final View child = group.getChildAt(i);
+ if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
+ y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
+ canScroll(child, true, dx, dy, x + scrollX - child.getLeft(),
+ y + scrollY - child.getTop())) {
+ return true;
+ }
+ }
+ }
+ return checkV && (ViewCompat.canScrollHorizontally(v, -dx) ||
+ ViewCompat.canScrollVertically(v, -dy));
+ }
+
+ /**
+ * Check if this event as provided to the parent view's onInterceptTouchEvent should
+ * cause the parent to intercept the touch event stream.
+ *
+ * @param ev MotionEvent provided to onInterceptTouchEvent
+ * @return true if the parent view should return true from onInterceptTouchEvent
+ */
+ public boolean shouldInterceptTouchEvent(MotionEvent ev) {
+ final int action = MotionEventCompat.getActionMasked(ev);
+ final int actionIndex = MotionEventCompat.getActionIndex(ev);
+ if (action == MotionEvent.ACTION_DOWN) {
+ // Reset things for a new event stream, just in case we didn't get
+ // the whole previous stream.
+ cancel();
+ }
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+ switch (action) {
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+ final int pointerId = MotionEventCompat.getPointerId(ev, 0);
+ saveInitialMotion(x, y, pointerId);
+ final View toCapture = findTopChildUnder((int) x, (int) y);
+ // Catch a settling view if possible.
+ if (toCapture == mCapturedView && mDragState == STATE_SETTLING) {
+ tryCaptureViewForDrag(toCapture, pointerId);
+ }
+ final int edgesTouched = mInitialEdgesTouched[pointerId];
+ if ((edgesTouched & mTrackingEdges) != 0) {
+ mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
+ }
+ break;
+ }
+ case MotionEventCompat.ACTION_POINTER_DOWN: {
+ final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
+ final float x = MotionEventCompat.getX(ev, actionIndex);
+ final float y = MotionEventCompat.getY(ev, actionIndex);
+ saveInitialMotion(x, y, pointerId);
+ // A ViewDragHelper can only manipulate one view at a time.
+ if (mDragState == STATE_IDLE) {
+ final int edgesTouched = mInitialEdgesTouched[pointerId];
+ if ((edgesTouched & mTrackingEdges) != 0) {
+ mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
+ }
+ } else if (mDragState == STATE_SETTLING) {
+ // Catch a settling view if possible.
+ final View toCapture = findTopChildUnder((int) x, (int) y);
+ if (toCapture == mCapturedView) {
+ tryCaptureViewForDrag(toCapture, pointerId);
+ }
+ }
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (mInitialMotionX == null || mInitialMotionY == null) break;
+ // First to cross a touch slop over a draggable view wins. Also report edge drags.
+ final int pointerCount = MotionEventCompat.getPointerCount(ev);
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = MotionEventCompat.getPointerId(ev, i);
+ // If pointer is invalid then skip the ACTION_MOVE.
+ if (!isValidPointerForActionMove(pointerId)) continue;
+ final float x = MotionEventCompat.getX(ev, i);
+ final float y = MotionEventCompat.getY(ev, i);
+ final float dx = x - mInitialMotionX[pointerId];
+ final float dy = y - mInitialMotionY[pointerId];
+ final View toCapture = findTopChildUnder((int) x, (int) y);
+ final boolean pastSlop = toCapture != null && checkTouchSlop(toCapture, dx, dy);
+ if (pastSlop) {
+ // check the callback's
+ // getView[Horizontal|Vertical]DragRange methods to know
+ // if you can move at all along an axis, then see if it
+ // would clamp to the same value. If you can't move at
+ // all in every dimension with a nonzero range, bail.
+ final int oldLeft = toCapture.getLeft();
+ final int targetLeft = oldLeft + (int) dx;
+ final int newLeft = mCallback.clampViewPositionHorizontal(toCapture,
+ targetLeft, (int) dx);
+ final int oldTop = toCapture.getTop();
+ final int targetTop = oldTop + (int) dy;
+ final int newTop = mCallback.clampViewPositionVertical(toCapture, targetTop,
+ (int) dy);
+ final int horizontalDragRange = mCallback.getViewHorizontalDragRange(
+ toCapture);
+ final int verticalDragRange = mCallback.getViewVerticalDragRange(toCapture);
+ if ((horizontalDragRange == 0 || horizontalDragRange > 0
+ && newLeft == oldLeft) && (verticalDragRange == 0
+ || verticalDragRange > 0 && newTop == oldTop)) {
+ break;
+ }
+ }
+ reportNewEdgeDrags(dx, dy, pointerId);
+ if (mDragState == STATE_DRAGGING) {
+ // Callback might have started an edge drag
+ break;
+ }
+ if (pastSlop && tryCaptureViewForDrag(toCapture, pointerId)) {
+ break;
+ }
+ }
+ saveLastMotion(ev);
+ break;
+ }
+ case MotionEventCompat.ACTION_POINTER_UP: {
+ final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
+ clearMotionHistory(pointerId);
+ break;
+ }
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL: {
+ cancel();
+ break;
+ }
+ }
+ return mDragState == STATE_DRAGGING;
+ }
+
+ /**
+ * Process a touch event received by the parent view. This method will dispatch callback events
+ * as needed before returning. The parent view's onTouchEvent implementation should call this.
+ *
+ * @param ev The touch event received by the parent view
+ */
+ public void processTouchEvent(MotionEvent ev) {
+ final int action = MotionEventCompat.getActionMasked(ev);
+ final int actionIndex = MotionEventCompat.getActionIndex(ev);
+ if (action == MotionEvent.ACTION_DOWN) {
+ // Reset things for a new event stream, just in case we didn't get
+ // the whole previous stream.
+ cancel();
+ }
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+ switch (action) {
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ final float y = ev.getY();
+ final int pointerId = MotionEventCompat.getPointerId(ev, 0);
+ final View toCapture = findTopChildUnder((int) x, (int) y);
+ saveInitialMotion(x, y, pointerId);
+ // Since the parent is already directly processing this touch event,
+ // there is no reason to delay for a slop before dragging.
+ // Start immediately if possible.
+ tryCaptureViewForDrag(toCapture, pointerId);
+ final int edgesTouched = mInitialEdgesTouched[pointerId];
+ if ((edgesTouched & mTrackingEdges) != 0) {
+ mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
+ }
+ break;
+ }
+ case MotionEventCompat.ACTION_POINTER_DOWN: {
+ final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
+ final float x = MotionEventCompat.getX(ev, actionIndex);
+ final float y = MotionEventCompat.getY(ev, actionIndex);
+ saveInitialMotion(x, y, pointerId);
+ // A ViewDragHelper can only manipulate one view at a time.
+ if (mDragState == STATE_IDLE) {
+ // If we're idle we can do anything! Treat it like a normal down event.
+ final View toCapture = findTopChildUnder((int) x, (int) y);
+ tryCaptureViewForDrag(toCapture, pointerId);
+ final int edgesTouched = mInitialEdgesTouched[pointerId];
+ if ((edgesTouched & mTrackingEdges) != 0) {
+ mCallback.onEdgeTouched(edgesTouched & mTrackingEdges, pointerId);
+ }
+ } else if (isCapturedViewUnder((int) x, (int) y)) {
+ // We're still tracking a captured view. If the same view is under this
+ // point, we'll swap to controlling it with this pointer instead.
+ // (This will still work if we're "catching" a settling view.)
+ tryCaptureViewForDrag(mCapturedView, pointerId);
+ }
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (mDragState == STATE_DRAGGING) {
+ // If pointer is invalid then skip the ACTION_MOVE.
+ if (!isValidPointerForActionMove(mActivePointerId)) break;
+ final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
+ final float x = MotionEventCompat.getX(ev, index);
+ final float y = MotionEventCompat.getY(ev, index);
+ final int idx = (int) (x - mLastMotionX[mActivePointerId]);
+ final int idy = (int) (y - mLastMotionY[mActivePointerId]);
+ dragTo(mCapturedView.getLeft() + idx, mCapturedView.getTop() + idy, idx, idy);
+ saveLastMotion(ev);
+ } else {
+ // Check to see if any pointer is now over a draggable view.
+ final int pointerCount = MotionEventCompat.getPointerCount(ev);
+ for (int i = 0; i < pointerCount; i++) {
+ final int pointerId = MotionEventCompat.getPointerId(ev, i);
+ // If pointer is invalid then skip the ACTION_MOVE.
+ if (!isValidPointerForActionMove(pointerId)) continue;
+ final float x = MotionEventCompat.getX(ev, i);
+ final float y = MotionEventCompat.getY(ev, i);
+ final float dx = x - mInitialMotionX[pointerId];
+ final float dy = y - mInitialMotionY[pointerId];
+ reportNewEdgeDrags(dx, dy, pointerId);
+ if (mDragState == STATE_DRAGGING) {
+ // Callback might have started an edge drag.
+ break;
+ }
+ final View toCapture = findTopChildUnder((int) x, (int) y);
+ if (checkTouchSlop(toCapture, dx, dy) &&
+ tryCaptureViewForDrag(toCapture, pointerId)) {
+ break;
+ }
+ }
+ saveLastMotion(ev);
+ }
+ break;
+ }
+ case MotionEventCompat.ACTION_POINTER_UP: {
+ final int pointerId = MotionEventCompat.getPointerId(ev, actionIndex);
+ if (mDragState == STATE_DRAGGING && pointerId == mActivePointerId) {
+ // Try to find another pointer that's still holding on to the captured view.
+ int newActivePointer = INVALID_POINTER;
+ final int pointerCount = MotionEventCompat.getPointerCount(ev);
+ for (int i = 0; i < pointerCount; i++) {
+ final int id = MotionEventCompat.getPointerId(ev, i);
+ if (id == mActivePointerId) {
+ // This one's going away, skip.
+ continue;
+ }
+ final float x = MotionEventCompat.getX(ev, i);
+ final float y = MotionEventCompat.getY(ev, i);
+ if (findTopChildUnder((int) x, (int) y) == mCapturedView &&
+ tryCaptureViewForDrag(mCapturedView, id)) {
+ newActivePointer = mActivePointerId;
+ break;
+ }
+ }
+ if (newActivePointer == INVALID_POINTER) {
+ // We didn't find another pointer still touching the view, release it.
+ releaseViewForPointerUp();
+ }
+ }
+ clearMotionHistory(pointerId);
+ break;
+ }
+ case MotionEvent.ACTION_UP: {
+ if (mDragState == STATE_DRAGGING) {
+ releaseViewForPointerUp();
+ }
+ cancel();
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL: {
+ if (mDragState == STATE_DRAGGING) {
+ dispatchViewReleased(0, 0);
+ }
+ cancel();
+ break;
+ }
+ }
+ }
+
+ private void reportNewEdgeDrags(float dx, float dy, int pointerId) {
+ int dragsStarted = 0;
+ if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_LEFT)) {
+ dragsStarted |= EDGE_LEFT;
+ }
+ if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_TOP)) {
+ dragsStarted |= EDGE_TOP;
+ }
+ if (checkNewEdgeDrag(dx, dy, pointerId, EDGE_RIGHT)) {
+ dragsStarted |= EDGE_RIGHT;
+ }
+ if (checkNewEdgeDrag(dy, dx, pointerId, EDGE_BOTTOM)) {
+ dragsStarted |= EDGE_BOTTOM;
+ }
+ if (dragsStarted != 0) {
+ mEdgeDragsInProgress[pointerId] |= dragsStarted;
+ mCallback.onEdgeDragStarted(dragsStarted, pointerId);
+ }
+ }
+
+ private boolean checkNewEdgeDrag(float delta, float odelta, int pointerId, int edge) {
+ final float absDelta = Math.abs(delta);
+ final float absODelta = Math.abs(odelta);
+ if ((mInitialEdgesTouched[pointerId] & edge) != edge || (mTrackingEdges & edge) == 0 ||
+ (mEdgeDragsLocked[pointerId] & edge) == edge ||
+ (mEdgeDragsInProgress[pointerId] & edge) == edge ||
+ (absDelta <= mTouchSlop && absODelta <= mTouchSlop)) {
+ return false;
+ }
+ if (absDelta < absODelta * 0.5f && mCallback.onEdgeLock(edge)) {
+ mEdgeDragsLocked[pointerId] |= edge;
+ return false;
+ }
+ return (mEdgeDragsInProgress[pointerId] & edge) == 0 && absDelta > mTouchSlop;
+ }
+
+ /**
+ * Check if we've crossed a reasonable touch slop for the given child view.
+ * If the child cannot be dragged along the horizontal or vertical axis, motion
+ * along that axis will not count toward the slop check.
+ *
+ * @param child Child to check
+ * @param dx Motion since initial position along X axis
+ * @param dy Motion since initial position along Y axis
+ * @return true if the touch slop has been crossed
+ */
+
+ private boolean checkTouchSlop(View child, float dx, float dy) {
+ if (child == null) {
+ return false;
+ }
+ final boolean checkHorizontal = mCallback.getViewHorizontalDragRange(child) > 0;
+ final boolean checkVertical = mCallback.getViewVerticalDragRange(child) > 0;
+
+ float temp_dy = dy;
+ if (temp_dy < 0)
+ temp_dy = -temp_dy;
+
+ if (checkHorizontal && checkVertical) {
+ return dx * dx + dy * dy > mTouchSlop * mTouchSlop;
+ } else if (checkVertical) {
+ return Math.abs(dy) > mTouchSlop;
+ } else if (checkHorizontal && 3 * temp_dy < dx) {
+ return Math.abs(dx) > mTouchSlop;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if any pointer tracked in the current gesture has crossed
+ * the required slop threshold.
+ * <p>
+ * <p>This depends on internal state populated by
+ * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
+ * {@link #processTouchEvent(android.view.MotionEvent)}. You should only rely on
+ * the results of this method after all currently available touch data
+ * has been provided to one of these two methods.</p>
+ *
+ * @param directions Combination of direction flags, see {@link #DIRECTION_HORIZONTAL},
+ * {@link #DIRECTION_VERTICAL}, {@link #DIRECTION_ALL}
+ * @return true if the slop threshold has been crossed, false otherwise
+ */
+ public boolean checkTouchSlop(int directions) {
+ final int count = mInitialMotionX.length;
+ for (int i = 0; i < count; i++) {
+ if (checkTouchSlop(directions, i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if the specified pointer tracked in the current gesture has crossed
+ * the required slop threshold.
+ * <p>
+ * <p>This depends on internal state populated by
+ * {@link #shouldInterceptTouchEvent(android.view.MotionEvent)} or
+ * {@link #processTouchEvent(android.view.MotionEvent)}. You should only rely on
+ * the results of this method after all currently available touch data
+ * has been provided to one of these two methods.</p>
+ *
+ * @param directions Combination of direction flags, see {@link #DIRECTION_HORIZONTAL},
+ * {@link #DIRECTION_VERTICAL}, {@link #DIRECTION_ALL}
+ * @param pointerId ID of the pointer to slop check as specified by MotionEvent
+ * @return true if the slop threshold has been crossed, false otherwise
+ */
+ public boolean checkTouchSlop(int directions, int pointerId) {
+ if (!isPointerDown(pointerId)) {
+ return false;
+ }
+ final boolean checkHorizontal = (directions & DIRECTION_HORIZONTAL) == DIRECTION_HORIZONTAL;
+ final boolean checkVertical = (directions & DIRECTION_VERTICAL) == DIRECTION_VERTICAL;
+ final float dx = mLastMotionX[pointerId] - mInitialMotionX[pointerId];
+ final float dy = mLastMotionY[pointerId] - mInitialMotionY[pointerId];
+ if (checkHorizontal && checkVertical) {
+ return dx * dx + dy * dy > mTouchSlop * mTouchSlop;
+ } else if (checkHorizontal) {
+ return Math.abs(dx) > mTouchSlop;
+ } else if (checkVertical) {
+ return Math.abs(dy) > mTouchSlop;
+ }
+ return false;
+ }
+
+ /**
+ * Check if any of the edges specified were initially touched in the currently active gesture.
+ * If there is no currently active gesture this method will return false.
+ *
+ * @param edges Edges to check for an initial edge touch. See {@link #EDGE_LEFT},
+ * {@link #EDGE_TOP}, {@link #EDGE_RIGHT}, {@link #EDGE_BOTTOM} and
+ * {@link #EDGE_ALL}
+ * @return true if any of the edges specified were initially touched in the current gesture
+ */
+ public boolean isEdgeTouched(int edges) {
+ final int count = mInitialEdgesTouched.length;
+ for (int i = 0; i < count; i++) {
+ if (isEdgeTouched(edges, i)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if any of the edges specified were initially touched by the pointer with
+ * the specified ID. If there is no currently active gesture or if there is no pointer with
+ * the given ID currently down this method will return false.
+ *
+ * @param edges Edges to check for an initial edge touch. See {@link #EDGE_LEFT},
+ * {@link #EDGE_TOP}, {@link #EDGE_RIGHT}, {@link #EDGE_BOTTOM} and
+ * {@link #EDGE_ALL}
+ * @return true if any of the edges specified were initially touched in the current gesture
+ */
+ public boolean isEdgeTouched(int edges, int pointerId) {
+ return isPointerDown(pointerId) && (mInitialEdgesTouched[pointerId] & edges) != 0;
+ }
+
+ private void releaseViewForPointerUp() {
+ mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
+ final float xvel = clampMag(
+ VelocityTrackerCompat.getXVelocity(mVelocityTracker, mActivePointerId),
+ mMinVelocity, mMaxVelocity);
+ final float yvel = clampMag(
+ VelocityTrackerCompat.getYVelocity(mVelocityTracker, mActivePointerId),
+ mMinVelocity, mMaxVelocity);
+ dispatchViewReleased(xvel, yvel);
+ }
+
+ private void dragTo(int left, int top, int dx, int dy) {
+ int clampedX = left;
+ int clampedY = top;
+ final int oldLeft = mCapturedView.getLeft();
+ final int oldTop = mCapturedView.getTop();
+ if (dx != 0) {
+ clampedX = mCallback.clampViewPositionHorizontal(mCapturedView, left, dx);
+ ViewCompat.offsetLeftAndRight(mCapturedView, clampedX - oldLeft);
+ }
+ if (dy != 0) {
+ clampedY = mCallback.clampViewPositionVertical(mCapturedView, top, dy);
+ ViewCompat.offsetTopAndBottom(mCapturedView, clampedY - oldTop);
+ }
+ if (dx != 0 || dy != 0) {
+ final int clampedDx = clampedX - oldLeft;
+ final int clampedDy = clampedY - oldTop;
+ mCallback.onViewPositionChanged(mCapturedView, clampedX, clampedY,
+ clampedDx, clampedDy);
+ }
+ }
+
+ /**
+ * Determine if the currently captured view is under the given point in the
+ * parent view's coordinate system. If there is no captured view this method
+ * will return false.
+ *
+ * @param x X position to test in the parent's coordinate system
+ * @param y Y position to test in the parent's coordinate system
+ * @return true if the captured view is under the given point, false otherwise
+ */
+ public boolean isCapturedViewUnder(int x, int y) {
+ return isViewUnder(mCapturedView, x, y);
+ }
+
+ /**
+ * Determine if the supplied view is under the given point in the
+ * parent view's coordinate system.
+ *
+ * @param view Child view of the parent to hit test
+ * @param x X position to test in the parent's coordinate system
+ * @param y Y position to test in the parent's coordinate system
+ * @return true if the supplied view is under the given point, false otherwise
+ */
+ public boolean isViewUnder(View view, int x, int y) {
+ if (view == null) {
+ return false;
+ }
+ return x >= view.getLeft() &&
+ x < view.getRight() &&
+ y >= view.getTop() &&
+ y < view.getBottom();
+ }
+
+ /**
+ * Find the topmost child under the given point within the parent view's coordinate system.
+ * The child order is determined using {@link Callback#getOrderedChildIndex(int)}.
+ *
+ * @param x X position to test in the parent's coordinate system
+ * @param y Y position to test in the parent's coordinate system
+ * @return The topmost child view under (x, y) or null if none found.
+ */
+ public View findTopChildUnder(int x, int y) {
+ final int childCount = mParentView.getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ final View child = mParentView.getChildAt(mCallback.getOrderedChildIndex(i));
+ if (x >= child.getLeft() && x < child.getRight() &&
+ y >= child.getTop() && y < child.getBottom()) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ private int getEdgesTouched(int x, int y) {
+ int result = 0;
+ if (x < mParentView.getLeft() + mEdgeSize) result |= EDGE_LEFT;
+ if (y < mParentView.getTop() + mEdgeSize) result |= EDGE_TOP;
+ if (x > mParentView.getRight() - mEdgeSize) result |= EDGE_RIGHT;
+ if (y > mParentView.getBottom() - mEdgeSize) result |= EDGE_BOTTOM;
+ return result;
+ }
+
+ private boolean isValidPointerForActionMove(int pointerId) {
+ if (!isPointerDown(pointerId)) {
+ Log.e(TAG, "Ignoring pointerId=" + pointerId + " because ACTION_DOWN was not received "
+ + "for this pointer before ACTION_MOVE. It likely happened because "
+ + " ViewDragHelper did not receive all the events in the event stream.");
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/ScrimRenderer.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/ScrimRenderer.java
new file mode 100644
index 00000000..9732d3b9
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/ScrimRenderer.java
@@ -0,0 +1,125 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.widget;
+
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrPosition;
+
+
+final class ScrimRenderer {
+
+ private final View rootView;
+ private final View decorView;
+ private final Rect dirtyRect;
+
+
+ ScrimRenderer(@NonNull View rootView, @NonNull View decorView) {
+ this.rootView = rootView;
+ this.decorView = decorView;
+ dirtyRect = new Rect();
+ }
+
+
+ void render(Canvas canvas, SlidrPosition position, Paint paint) {
+ switch (position) {
+ case LEFT:
+ renderLeft(canvas, paint);
+ break;
+ case RIGHT:
+ renderRight(canvas, paint);
+ break;
+ case TOP:
+ renderTop(canvas, paint);
+ break;
+ case BOTTOM:
+ renderBottom(canvas, paint);
+ break;
+ case VERTICAL:
+ renderVertical(canvas, paint);
+ break;
+ case HORIZONTAL:
+ renderHorizontal(canvas, paint);
+ break;
+ }
+ }
+
+
+ Rect getDirtyRect(SlidrPosition position) {
+ switch (position) {
+ case LEFT:
+ dirtyRect.set(0, 0, decorView.getLeft(), rootView.getMeasuredHeight());
+ break;
+ case RIGHT:
+ dirtyRect.set(decorView.getRight(), 0, rootView.getMeasuredWidth(), rootView.getMeasuredHeight());
+ break;
+ case TOP:
+ dirtyRect.set(0, 0, rootView.getMeasuredWidth(), decorView.getTop());
+ break;
+ case BOTTOM:
+ dirtyRect.set(0, decorView.getBottom(), rootView.getMeasuredWidth(), rootView.getMeasuredHeight());
+ break;
+ case VERTICAL:
+ if (decorView.getTop() > 0) {
+ dirtyRect.set(0, 0, rootView.getMeasuredWidth(), decorView.getTop());
+ }
+ else {
+ dirtyRect.set(0, decorView.getBottom(), rootView.getMeasuredWidth(), rootView.getMeasuredHeight());
+ }
+ break;
+ case HORIZONTAL:
+ if (decorView.getLeft() > 0) {
+ dirtyRect.set(0, 0, decorView.getLeft(), rootView.getMeasuredHeight());
+ }
+ else {
+ dirtyRect.set(decorView.getRight(), 0, rootView.getMeasuredWidth(), rootView.getMeasuredHeight());
+ }
+ break;
+ }
+ return dirtyRect;
+ }
+
+
+ private void renderLeft(Canvas canvas, Paint paint) {
+ canvas.drawRect(0, 0, decorView.getLeft(), rootView.getMeasuredHeight(), paint);
+ }
+
+
+ private void renderRight(Canvas canvas, Paint paint) {
+ canvas.drawRect(decorView.getRight(), 0, rootView.getMeasuredWidth(), rootView.getMeasuredHeight(), paint);
+ }
+
+
+ private void renderTop(Canvas canvas, Paint paint) {
+ canvas.drawRect(0, 0, rootView.getMeasuredWidth(), decorView.getTop(), paint);
+ }
+
+
+ private void renderBottom(Canvas canvas, Paint paint) {
+ canvas.drawRect(0, decorView.getBottom(), rootView.getMeasuredWidth(), rootView.getMeasuredHeight(), paint);
+ }
+
+
+ private void renderVertical(Canvas canvas, Paint paint) {
+ if (decorView.getTop() > 0) {
+ renderTop(canvas, paint);
+ }
+ else {
+ renderBottom(canvas, paint);
+ }
+ }
+
+
+ private void renderHorizontal(Canvas canvas, Paint paint) {
+ if (decorView.getLeft() > 0) {
+ renderLeft(canvas, paint);
+ }
+ else {
+ renderRight(canvas, paint);
+ }
+ }
+}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/SliderPanel.java b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/SliderPanel.java
new file mode 100644
index 00000000..fe8ea871
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/customviews/slidr/widget/SliderPanel.java
@@ -0,0 +1,782 @@
+package ml.docilealligator.infinityforreddit.customviews.slidr.widget;
+
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.core.view.ViewCompat;
+import androidx.core.view.ViewGroupCompat;
+
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrConfig;
+import ml.docilealligator.infinityforreddit.customviews.slidr.model.SlidrInterface;
+import ml.docilealligator.infinityforreddit.customviews.slidr.util.ViewDragHelper;
+
+
+public class SliderPanel extends FrameLayout {
+
+ private static final int MIN_FLING_VELOCITY = 400; // dips per second
+
+ private int screenWidth;
+ private int screenHeight;
+
+ private View decorView;
+ private ViewDragHelper dragHelper;
+ private OnPanelSlideListener listener;
+ private Paint scrimPaint;
+ private ScrimRenderer scrimRenderer;
+
+ private boolean isLocked = false;
+ private boolean isEdgeTouched = false;
+ private int edgePosition;
+
+ private SlidrConfig config;
+
+
+ public SliderPanel(Context context) {
+ super(context);
+ }
+
+
+ public SliderPanel(Context context, View decorView, SlidrConfig config){
+ super(context);
+ this.decorView = decorView;
+ this.config = (config == null ? new SlidrConfig.Builder().build() : config);
+ init();
+ }
+
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ boolean interceptForDrag;
+
+ if(isLocked){
+ return false;
+ }
+
+ if(config.isEdgeOnly()) {
+ isEdgeTouched = canDragFromEdge(ev);
+ }
+
+ // Fix for pull request #13 and issue #12
+ try {
+ interceptForDrag = dragHelper.shouldInterceptTouchEvent(ev);
+ } catch (Exception e) {
+ interceptForDrag = false;
+ }
+
+ return interceptForDrag && !isLocked;
+ }
+
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if(isLocked){
+ return false;
+ }
+
+ try {
+ dragHelper.processTouchEvent(event);
+ }catch (IllegalArgumentException e){
+ return false;
+ }
+
+ return true;
+ }
+
+
+ @Override
+ public void computeScroll() {
+ super.computeScroll();
+ if(dragHelper.continueSettling(true)){
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ scrimRenderer.render(canvas, config.getPosition(), scrimPaint);
+ }
+
+
+ /**
+ * Set the panel slide listener that gets called based on slider changes
+ * @param listener callback implementation
+ */
+ public void setOnPanelSlideListener(OnPanelSlideListener listener){
+ this.listener = listener;
+ }
+
+
+ /**
+ * Get the default {@link SlidrInterface} from which to control the panel with after attachment
+ */
+ public SlidrInterface getDefaultInterface() {
+ return defaultSlidrInterface;
+ }
+
+
+ private final SlidrInterface defaultSlidrInterface = new SlidrInterface() {
+
+
+ @Override
+ public void lock() {
+ SliderPanel.this.lock();
+ }
+
+
+ @Override
+ public void unlock() {
+ SliderPanel.this.unlock();
+ }
+ };
+
+
+ /**
+ * The drag helper callback interface for the Left position
+ */
+ private final ViewDragHelper.Callback leftCallback = new ViewDragHelper.Callback() {
+
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ boolean edgeCase = !config.isEdgeOnly() || dragHelper.isEdgeTouched(edgePosition, pointerId);
+ return child.getId() == decorView.getId() && edgeCase;
+ }
+
+ @Override
+ public int clampViewPositionHorizontal(View child, int left, int dx) {
+ return clamp(left, 0, screenWidth);
+ }
+
+ @Override
+ public int getViewHorizontalDragRange(View child) {
+ return screenWidth;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ super.onViewReleased(releasedChild, xvel, yvel);
+
+ int left = releasedChild.getLeft();
+ int settleLeft = 0;
+ int leftThreshold = (int) (getWidth() * config.getDistanceThreshold());
+ boolean isVerticalSwiping = Math.abs(yvel) > config.getVelocityThreshold();
+
+ if(xvel > 0){
+
+ if(Math.abs(xvel) > config.getVelocityThreshold() && !isVerticalSwiping){
+ settleLeft = screenWidth;
+ }else if(left > leftThreshold){
+ settleLeft = screenWidth;
+ }
+
+ }else if(xvel == 0){
+ if(left > leftThreshold){
+ settleLeft = screenWidth;
+ }
+ }
+
+ dragHelper.settleCapturedViewAt(settleLeft, releasedChild.getTop());
+ invalidate();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ super.onViewPositionChanged(changedView, left, top, dx, dy);
+ float percent = 1f - ((float)left / (float) screenWidth);
+
+ if(listener != null) listener.onSlideChange(percent);
+
+ // Update the dimmer alpha
+ applyScrim(percent);
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ super.onViewDragStateChanged(state);
+ if(listener != null) listener.onStateChanged(state);
+ switch (state){
+ case ViewDragHelper.STATE_IDLE:
+ if(decorView.getLeft() == 0){
+ // State Open
+ if(listener != null) listener.onOpened();
+ }else{
+ // State Closed
+ if(listener != null) listener.onClosed();
+ }
+ break;
+ case ViewDragHelper.STATE_DRAGGING:
+
+ break;
+ case ViewDragHelper.STATE_SETTLING:
+
+ break;
+ }
+ }
+
+ };
+
+
+ /**
+ * The drag helper callbacks for dragging the slidr attachment from the right of the screen
+ */
+ private final ViewDragHelper.Callback rightCallback = new ViewDragHelper.Callback() {
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ boolean edgeCase = !config.isEdgeOnly() || dragHelper.isEdgeTouched(edgePosition, pointerId);
+ return child.getId() == decorView.getId() && edgeCase;
+ }
+
+ @Override
+ public int clampViewPositionHorizontal(View child, int left, int dx) {
+ return clamp(left, -screenWidth, 0);
+ }
+
+ @Override
+ public int getViewHorizontalDragRange(View child) {
+ return screenWidth;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ super.onViewReleased(releasedChild, xvel, yvel);
+
+ int left = releasedChild.getLeft();
+ int settleLeft = 0;
+ int leftThreshold = (int) (getWidth() * config.getDistanceThreshold());
+ boolean isVerticalSwiping = Math.abs(yvel) > config.getVelocityThreshold();
+
+ if(xvel < 0){
+
+ if(Math.abs(xvel) > config.getVelocityThreshold() && !isVerticalSwiping){
+ settleLeft = -screenWidth;
+ }else if(left < -leftThreshold){
+ settleLeft = -screenWidth;
+ }
+
+ }else if(xvel == 0){
+ if(left < -leftThreshold){
+ settleLeft = -screenWidth;
+ }
+ }
+
+ dragHelper.settleCapturedViewAt(settleLeft, releasedChild.getTop());
+ invalidate();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ super.onViewPositionChanged(changedView, left, top, dx, dy);
+ float percent = 1f - ((float)Math.abs(left) / (float) screenWidth);
+
+ if(listener != null) listener.onSlideChange(percent);
+
+ // Update the dimmer alpha
+ applyScrim(percent);
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ super.onViewDragStateChanged(state);
+ if(listener != null) listener.onStateChanged(state);
+ switch (state){
+ case ViewDragHelper.STATE_IDLE:
+ if(decorView.getLeft() == 0){
+ // State Open
+ if(listener != null) listener.onOpened();
+ }else{
+ // State Closed
+ if(listener != null) listener.onClosed();
+ }
+ break;
+ case ViewDragHelper.STATE_DRAGGING:
+
+ break;
+ case ViewDragHelper.STATE_SETTLING:
+
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * The drag helper callbacks for dragging the slidr attachment from the top of the screen
+ */
+ private final ViewDragHelper.Callback topCallback = new ViewDragHelper.Callback() {
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ return child.getId() == decorView.getId() && (!config.isEdgeOnly() || isEdgeTouched);
+ }
+
+ @Override
+ public int clampViewPositionVertical(View child, int top, int dy) {
+ return clamp(top, 0, screenHeight);
+ }
+
+ @Override
+ public int getViewVerticalDragRange(View child) {
+ return screenHeight;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ super.onViewReleased(releasedChild, xvel, yvel);
+
+ int top = releasedChild.getTop();
+ int settleTop = 0;
+ int topThreshold = (int) (getHeight() * config.getDistanceThreshold());
+ boolean isSideSwiping = Math.abs(xvel) > config.getVelocityThreshold();
+
+ if(yvel > 0){
+ if(Math.abs(yvel) > config.getVelocityThreshold() && !isSideSwiping){
+ settleTop = screenHeight;
+ }else if(top > topThreshold){
+ settleTop = screenHeight;
+ }
+ }else if(yvel == 0){
+ if(top > topThreshold){
+ settleTop = screenHeight;
+ }
+ }
+
+ dragHelper.settleCapturedViewAt(releasedChild.getLeft(), settleTop);
+ invalidate();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ super.onViewPositionChanged(changedView, left, top, dx, dy);
+ float percent = 1f - ((float)Math.abs(top) / (float) screenHeight);
+
+ if(listener != null) listener.onSlideChange(percent);
+
+ // Update the dimmer alpha
+ applyScrim(percent);
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ super.onViewDragStateChanged(state);
+ if(listener != null) listener.onStateChanged(state);
+ switch (state){
+ case ViewDragHelper.STATE_IDLE:
+ if(decorView.getTop() == 0){
+ // State Open
+ if(listener != null) listener.onOpened();
+ }else{
+ // State Closed
+ if(listener != null) listener.onClosed();
+ }
+ break;
+ case ViewDragHelper.STATE_DRAGGING:
+
+ break;
+ case ViewDragHelper.STATE_SETTLING:
+
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * The drag helper callbacks for dragging the slidr attachment from the bottom of hte screen
+ */
+ private final ViewDragHelper.Callback bottomCallback = new ViewDragHelper.Callback() {
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ return child.getId() == decorView.getId() && (!config.isEdgeOnly() || isEdgeTouched);
+ }
+
+ @Override
+ public int clampViewPositionVertical(View child, int top, int dy) {
+ return clamp(top, -screenHeight, 0);
+ }
+
+ @Override
+ public int getViewVerticalDragRange(View child) {
+ return screenHeight;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ super.onViewReleased(releasedChild, xvel, yvel);
+
+ int top = releasedChild.getTop();
+ int settleTop = 0;
+ int topThreshold = (int) (getHeight() * config.getDistanceThreshold());
+ boolean isSideSwiping = Math.abs(xvel) > config.getVelocityThreshold();
+
+ if(yvel < 0){
+ if(Math.abs(yvel) > config.getVelocityThreshold() && !isSideSwiping){
+ settleTop = -screenHeight;
+ }else if(top < -topThreshold){
+ settleTop = -screenHeight;
+ }
+ }else if(yvel == 0){
+ if(top < -topThreshold){
+ settleTop = -screenHeight;
+ }
+ }
+
+ dragHelper.settleCapturedViewAt(releasedChild.getLeft(), settleTop);
+ invalidate();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ super.onViewPositionChanged(changedView, left, top, dx, dy);
+ float percent = 1f - ((float)Math.abs(top) / (float) screenHeight);
+
+ if(listener != null) listener.onSlideChange(percent);
+
+ // Update the dimmer alpha
+ applyScrim(percent);
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ super.onViewDragStateChanged(state);
+ if(listener != null) listener.onStateChanged(state);
+ switch (state){
+ case ViewDragHelper.STATE_IDLE:
+ if(decorView.getTop() == 0){
+ // State Open
+ if(listener != null) listener.onOpened();
+ }else{
+ // State Closed
+ if(listener != null) listener.onClosed();
+ }
+ break;
+ case ViewDragHelper.STATE_DRAGGING:
+
+ break;
+ case ViewDragHelper.STATE_SETTLING:
+
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * The drag helper callbacks for dragging the slidr attachment in both vertical directions
+ */
+ private final ViewDragHelper.Callback verticalCallback = new ViewDragHelper.Callback() {
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ return child.getId() == decorView.getId() && (!config.isEdgeOnly() || isEdgeTouched);
+ }
+
+ @Override
+ public int clampViewPositionVertical(View child, int top, int dy) {
+ return clamp(top, -screenHeight, screenHeight);
+ }
+
+ @Override
+ public int getViewVerticalDragRange(View child) {
+ return screenHeight;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ super.onViewReleased(releasedChild, xvel, yvel);
+
+ int top = releasedChild.getTop();
+ int settleTop = 0;
+ int topThreshold = (int) (getHeight() * config.getDistanceThreshold());
+ boolean isSideSwiping = Math.abs(xvel) > config.getVelocityThreshold();
+
+ if(yvel > 0){
+
+ // Being slinged down
+ if(Math.abs(yvel) > config.getVelocityThreshold() && !isSideSwiping){
+ settleTop = screenHeight;
+ }else if(top > topThreshold){
+ settleTop = screenHeight;
+ }
+
+ }else if(yvel < 0){
+ // Being slinged up
+ if(Math.abs(yvel) > config.getVelocityThreshold() && !isSideSwiping){
+ settleTop = -screenHeight;
+ }else if(top < -topThreshold){
+ settleTop = -screenHeight;
+ }
+
+ }else{
+
+ if(top > topThreshold){
+ settleTop = screenHeight;
+ }else if(top < -topThreshold){
+ settleTop = -screenHeight;
+ }
+
+ }
+
+ dragHelper.settleCapturedViewAt(releasedChild.getLeft(), settleTop);
+ invalidate();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ super.onViewPositionChanged(changedView, left, top, dx, dy);
+ float percent = 1f - ((float)Math.abs(top) / (float) screenHeight);
+
+ if(listener != null) listener.onSlideChange(percent);
+
+ // Update the dimmer alpha
+ applyScrim(percent);
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ super.onViewDragStateChanged(state);
+ if(listener != null) listener.onStateChanged(state);
+ switch (state){
+ case ViewDragHelper.STATE_IDLE:
+ if(decorView.getTop() == 0){
+ // State Open
+ if(listener != null) listener.onOpened();
+ }else{
+ // State Closed
+ if(listener != null) listener.onClosed();
+ }
+ break;
+ case ViewDragHelper.STATE_DRAGGING:
+
+ break;
+ case ViewDragHelper.STATE_SETTLING:
+
+ break;
+ }
+ }
+ };
+
+
+ /**
+ * The drag helper callbacks for dragging the slidr attachment in both horizontal directions
+ */
+ private final ViewDragHelper.Callback horizontalCallback = new ViewDragHelper.Callback() {
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ boolean edgeCase = !config.isEdgeOnly() || dragHelper.isEdgeTouched(edgePosition, pointerId);
+ return child.getId() == decorView.getId() && edgeCase;
+ }
+
+ @Override
+ public int clampViewPositionHorizontal(View child, int left, int dx) {
+ return clamp(left, -screenWidth, screenWidth);
+ }
+
+ @Override
+ public int getViewHorizontalDragRange(View child) {
+ return screenWidth;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ super.onViewReleased(releasedChild, xvel, yvel);
+
+ int left = releasedChild.getLeft();
+ int settleLeft = 0;
+ int leftThreshold = (int) (getWidth() * config.getDistanceThreshold());
+ boolean isVerticalSwiping = Math.abs(yvel) > config.getVelocityThreshold();
+
+ if(xvel > 0){
+
+ if(Math.abs(xvel) > config.getVelocityThreshold() && !isVerticalSwiping){
+ settleLeft = screenWidth;
+ }else if(left > leftThreshold){
+ settleLeft = screenWidth;
+ }
+
+ }else if(xvel < 0){
+
+ if(Math.abs(xvel) > config.getVelocityThreshold() && !isVerticalSwiping){
+ settleLeft = -screenWidth;
+ }else if(left < -leftThreshold){
+ settleLeft = -screenWidth;
+ }
+
+ }else{
+ if(left > leftThreshold){
+ settleLeft = screenWidth;
+ }else if(left < -leftThreshold){
+ settleLeft = -screenWidth;
+ }
+ }
+
+ dragHelper.settleCapturedViewAt(settleLeft, releasedChild.getTop());
+ invalidate();
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ super.onViewPositionChanged(changedView, left, top, dx, dy);
+ float percent = 1f - ((float)Math.abs(left) / (float) screenWidth);
+
+ if(listener != null) listener.onSlideChange(percent);
+
+ // Update the dimmer alpha
+ applyScrim(percent);
+ }
+
+ @Override
+ public void onViewDragStateChanged(int state) {
+ super.onViewDragStateChanged(state);
+ if(listener != null) listener.onStateChanged(state);
+ switch (state){
+ case ViewDragHelper.STATE_IDLE:
+ if(decorView.getLeft() == 0){
+ // State Open
+ if(listener != null) listener.onOpened();
+ }else{
+ // State Closed
+ if(listener != null) listener.onClosed();
+ }
+ break;
+ case ViewDragHelper.STATE_DRAGGING:
+
+ break;
+ case ViewDragHelper.STATE_SETTLING:
+
+ break;
+ }
+ }
+ };
+
+
+ private void init(){
+ setWillNotDraw(false);
+ screenWidth = getResources().getDisplayMetrics().widthPixels;
+
+ final float density = getResources().getDisplayMetrics().density;
+ final float minVel = MIN_FLING_VELOCITY * density;
+
+ ViewDragHelper.Callback callback;
+ switch (config.getPosition()){
+ case LEFT:
+ callback = leftCallback;
+ edgePosition = ViewDragHelper.EDGE_LEFT;
+ break;
+ case RIGHT:
+ callback = rightCallback;
+ edgePosition = ViewDragHelper.EDGE_RIGHT;
+ break;
+ case TOP:
+ callback = topCallback;
+ edgePosition = ViewDragHelper.EDGE_TOP;
+ break;
+ case BOTTOM:
+ callback = bottomCallback;
+ edgePosition = ViewDragHelper.EDGE_BOTTOM;
+ break;
+ case VERTICAL:
+ callback = verticalCallback;
+ edgePosition = ViewDragHelper.EDGE_TOP | ViewDragHelper.EDGE_BOTTOM;
+ break;
+ case HORIZONTAL:
+ callback = horizontalCallback;
+ edgePosition = ViewDragHelper.EDGE_LEFT | ViewDragHelper.EDGE_RIGHT;
+ break;
+ default:
+ callback = leftCallback;
+ edgePosition = ViewDragHelper.EDGE_LEFT;
+ }
+
+ dragHelper = ViewDragHelper.create(this, config.getSensitivity(), callback);
+ dragHelper.setMinVelocity(minVel);
+ dragHelper.setEdgeTrackingEnabled(edgePosition);
+
+ ViewGroupCompat.setMotionEventSplittingEnabled(this, false);
+
+ // Setup the dimmer view
+ scrimPaint = new Paint();
+ scrimPaint.setColor(config.getScrimColor());
+ scrimPaint.setAlpha(toAlpha(config.getScrimStartAlpha()));
+ scrimRenderer = new ScrimRenderer(this, decorView);
+
+ /*
+ * This is so we can get the height of the view and
+ * ignore the system navigation that would be included if we
+ * retrieved this value from the DisplayMetrics
+ */
+ post(new Runnable() {
+ @Override
+ public void run() {
+ screenHeight = getHeight();
+ }
+ });
+
+ }
+
+
+ public void lock(){
+ dragHelper.abort();
+ isLocked = true;
+ }
+
+
+ public void unlock(){
+ dragHelper.abort();
+ isLocked = false;
+ }
+
+
+ private boolean canDragFromEdge(MotionEvent ev) {
+ float x = ev.getX();
+ float y = ev.getY();
+
+ switch (config.getPosition()) {
+ case LEFT:
+ return x < config.getEdgeSize(getWidth());
+ case RIGHT:
+ return x > getWidth() - config.getEdgeSize(getWidth());
+ case BOTTOM:
+ return y > getHeight() - config.getEdgeSize(getHeight());
+ case TOP:
+ return y < config.getEdgeSize(getHeight());
+ case HORIZONTAL:
+ return x < config.getEdgeSize(getWidth()) || x > getWidth() - config.getEdgeSize(getWidth());
+ case VERTICAL:
+ return y < config.getEdgeSize(getHeight()) || y > getHeight() - config.getEdgeSize(getHeight());
+ }
+ return false;
+ }
+
+
+ private void applyScrim(float percent){
+ float alpha = (percent * (config.getScrimStartAlpha() - config.getScrimEndAlpha())) + config.getScrimEndAlpha();
+ scrimPaint.setAlpha(toAlpha(alpha));
+ invalidate(scrimRenderer.getDirtyRect(config.getPosition()));
+ }
+
+
+ private static int clamp(int value, int min, int max){
+ return Math.max(min, Math.min(max, value));
+ }
+
+
+ private static int toAlpha(float percentage) {
+ return (int) (percentage * 255);
+ }
+
+
+ /**
+ * The panel sliding interface that gets called
+ * whenever the panel is closed or opened
+ */
+ public interface OnPanelSlideListener{
+ void onStateChanged(int state);
+ void onClosed();
+ void onOpened();
+ void onSlideChange(float percent);
+ }
+
+}
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index ef5f352b..7d93b10e 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -1205,5 +1205,5 @@ Toque para volver a intentarlo."</string>
<string name="message_change_banner_success">"Banner cambiado correctamente"</string>
<string name="message_change_banner_failed">"Error al cambiar banner %s"</string>
<string name="message_save_profile_success">"Perfil guardado correctamente"</string>
- <string name="message_save_profile_failed">"Error al guardar perfil"</string>
+ <string name="message_save_profile_failed">Error al guardar perfil %s</string>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml
index 89e00bab..ca970d58 100644
--- a/app/src/main/res/values-vi/strings.xml
+++ b/app/src/main/res/values-vi/strings.xml
@@ -1159,11 +1159,11 @@ Nhấn để thử lại."</string>
<string name="message_remove_avatar_success">"Xoá ảnh đại diện thành công"</string>
<string name="message_remove_avatar_failed">"Xoá ảnh đại diện %s thất bại"</string>
<string name="message_remove_banner_success">"Xoá banner thành công"</string>
- <string name="message_remove_banner_failed">"Gỡ bỏ banner thất bại"</string>
+ <string name="message_remove_banner_failed">Gỡ bỏ banner thất bại %s</string>
<string name="message_change_avatar_success">"Thay đổi ảnh đại diện thành công"</string>
- <string name="message_change_avatar_failed">"Thay đổi ảnh đại diện thất bại"</string>
+ <string name="message_change_avatar_failed">Thay đổi ảnh đại diện thất bại %s</string>
<string name="message_change_banner_success">"Thay đổi banner thành công"</string>
- <string name="message_change_banner_failed">"Thay đổi banner thất bại"</string>
+ <string name="message_change_banner_failed">Thay đổi banner thất bại %s</string>
<string name="message_save_profile_success">"Lưu Hồ sơ thành công"</string>
<string name="message_save_profile_failed">"Lưu hồ sơ %s thất bại"</string>
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml
new file mode 100644
index 00000000..5c3016d2
--- /dev/null
+++ b/app/src/main/res/values/ids.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="slidable_panel" type="id" />
+ <item name="slidable_content" type="id" />
+</resources> \ No newline at end of file