diff --git a/README.md b/README.md
index 8061248..1226187 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@ This project is a light open-source library that improves the sharing experience
* [Picasso](#picasso)
* [Glide](#glide)
* [Custom icon loader](#custom-icon-loader)
+* [Comparator Provider](#comparator-provider)
* [What's next](#whats-next)
* [Contributing](#contributing)
* [License](#license)
@@ -45,7 +46,7 @@ Find more about our motivations [here](http://tvbarthel.fr/IntentShare/).
# Gradle dependency
available on jcenter.
```groovy
-compile 'fr.tvbarthel.intentshare:library:0.0.1'
+compile 'fr.tvbarthel.intentshare:library:0.0.2'
```
dependencies
@@ -213,7 +214,7 @@ Default icon loader used to load target activities icons is based on AsyncTask.
## Picasso
If your are already using Picasso, you may want to consider using PicassoIconLoader:
```groovy
-compile 'fr.tvbarthel.intentshare:picasso-loader:0.0.1'
+compile 'fr.tvbarthel.intentshare:picasso-loader:0.0.2'
```
```java
@@ -227,7 +228,7 @@ IntentShare.with(context)
## Glide
If your are already using Glide, you may want to consider using GlideIconLoader:
```groovy
-compile 'fr.tvbarthel.intentshare:glide-loader:0.0.1'
+compile 'fr.tvbarthel.intentshare:glide-loader:0.0.2'
```
```java
@@ -257,12 +258,52 @@ IntentShare.with(context)
})
.deliver();
```
+# Comparator provider
+By default, target activities are sorted based on the recency of their selection from your app.
+```java
+ /**
+ * Comparator used to sort {@link TargetActivity} based on the recency of their previous
+ * selection and their default order as fallback when they have never been selected.
+ *
+ * The ordering imposed by this comparator on a set of {@link TargetActivity}
+ * is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean
+ * value as e1.equals(e2).
+ */
+ public RecencyComparatorProvider() {
+
+ }
+```
+Instead of using the default comparator, you can implement your own comparator provider in order to customize the target activities order display to the user:
+```java
+/**
+ * ˙Interface which allow to define which comparator will be provided for sorting the
+ * target activity inside the {@link TargetChooserActivity}.
+ */
+public interface TargetActivityComparatorProvider extends Parcelable {
+
+ /**
+ * Provide the comparator used to sort {@link TargetActivity} displayed to the user.
+ *
+ * @return comparator used to sort {@link TargetActivity} displayed to the user.
+ */
+ Comparator provideComparator();
+}
+```
+```java
+IntentShare.with(context)
+ .chooserTitle("Select a sharing target : ")
+ .text("Default text you would like to share.")
+ .comparatorProvider(customComparatorProvider)
+ .deliver();
+```
+An example from the sample can be found here : [SocialTargetActivityComparatorProvider.java](https://github.com/tvbarthel/IntentShare/blob/develop/sample/src/main/java/fr/tvbarthel/intentsharesample/SocialTargetActivityComparatorProvider.java)
+
+
# What's next
- * Providing custom sorting for target activities.
* Providing easier way to share images.
* Removing dependencies on support libraries.
* Sample : implementing image selection for extra provider.
-
+
# Contributing
Contributions are very welcome (: You can contribute through GitHub by forking the repository and sending a pull request.
diff --git a/build.gradle b/build.gradle
index 42e3725..794acdf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.5.0'
+ classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
// NOTE: Do not place your application dependencies here; they belong
@@ -29,6 +29,6 @@ ext {
compileSdkVersion = 23
targetSdkVersion = 23
minSdkVersion = 16
- versionCode = 1
- versionName = "0.0.1"
+ versionCode = 2
+ versionName = "0.0.2"
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 6e24824..4f0f661 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/IntentShare.java b/library/src/main/java/fr/tvbarthel/intentshare/IntentShare.java
index f278128..91c0fa1 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/IntentShare.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/IntentShare.java
@@ -76,6 +76,11 @@ public IntentShare[] newArray(int size) {
*/
IconLoader iconLoader;
+ /**
+ * Provide the comparator used to sort the target activities.
+ */
+ TargetActivityComparatorProvider comparatorProvider;
+
/**
* Title that will be displayed in the chooser.
*/
@@ -99,6 +104,7 @@ private IntentShare(Context context) {
packageWithExtraProvider = new ArrayList<>();
this.listener = null;
this.iconLoader = new AsyncIconLoader();
+ this.comparatorProvider = new TargetActivity.RecencyComparatorProvider();
this.chooserTitle = context.getString(R.string.isl_default_sharing_label);
}
@@ -115,6 +121,7 @@ protected IntentShare(Parcel in) {
this.mailSubject = in.readString();
this.extraProviders = in.createTypedArrayList(ExtraProvider.CREATOR);
this.iconLoader = in.readParcelable(IconLoader.class.getClassLoader());
+ this.comparatorProvider = in.readParcelable(TargetActivityComparatorProvider.class.getClassLoader());
this.chooserTitle = in.readString();
}
@@ -131,6 +138,7 @@ public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mailSubject);
dest.writeTypedList(this.extraProviders);
dest.writeParcelable(this.iconLoader, flags);
+ dest.writeParcelable(this.comparatorProvider, flags);
dest.writeString(this.chooserTitle);
}
@@ -170,6 +178,26 @@ public IntentShare iconLoader(@NonNull IconLoader iconLoader) {
return this;
}
+ /**
+ * Provide a custom {@link java.util.Comparator} in order to sort the {@link TargetActivity}
+ * displayed to the user.
+ *
+ * By default, TargetActivities are sorted by the recentness of their selection. If it's the
+ * behaviour that you are looking for, don't use this method and let the default comparator
+ * bring the magic.
+ *
+ * @param comparatorProvider comparator used to sort the TargetActivities displayed to the user.
+ * Will override the default sorting by recentness.
+ * @return current {@link IntentShare} for method chaining.
+ */
+ public IntentShare comparatorProvider(@NonNull TargetActivityComparatorProvider comparatorProvider) {
+ if (comparatorProvider == null) {
+ throw new NullPointerException("Custom comparator provider can't be null.");
+ }
+ this.comparatorProvider = comparatorProvider;
+ return this;
+ }
+
/**
* Text which will be shared.
*
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/LayoutManagerFactory.java b/library/src/main/java/fr/tvbarthel/intentshare/LayoutManagerFactory.java
new file mode 100644
index 0000000..f9fba6c
--- /dev/null
+++ b/library/src/main/java/fr/tvbarthel/intentshare/LayoutManagerFactory.java
@@ -0,0 +1,55 @@
+package fr.tvbarthel.intentshare;
+
+import android.content.Context;
+import android.os.Build;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+
+/**
+ * Factory used to handle layout manager according to the device android version seamlessly
+ */
+final class LayoutManagerFactory {
+
+ private static final int MARSHMALLOW_SPAN_COUNT = 4;
+
+ /**
+ * Non instantiable class.
+ */
+ private LayoutManagerFactory() {
+
+ }
+
+ /**
+ * Build the layout manager for the {@link TargetActivity} list displayed to the user
+ * during the target activity selection.
+ *
+ * @param context context used to instantiate layout manager.
+ * @return layout manager matching the native look and feel linked to the device SDK version.
+ */
+ public static RecyclerView.LayoutManager buildLayoutManager(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ GridLayoutManager gridLayoutManager = new GridLayoutManager(context, MARSHMALLOW_SPAN_COUNT);
+ gridLayoutManager.setSpanSizeLookup(new MarshmallowSpanSizeLookup());
+ return gridLayoutManager;
+ } else {
+ return new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
+ }
+ }
+
+ /**
+ * SpanSizeLookup used to fit the native look and feel provided by
+ * {@link android.content.Intent#createChooser(android.content.Intent, CharSequence)}
+ */
+ private static final class MarshmallowSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {
+
+ @Override
+ public int getSpanSize(int position) {
+ if (position == 0) {
+ return MARSHMALLOW_SPAN_COUNT; // header taking the full width;
+ } else {
+ return 1; // target activity taking one unit;
+ }
+ }
+ }
+}
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java
index d2901e6..5e44238 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivity.java
@@ -3,15 +3,15 @@
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.net.Uri;
+import android.os.Parcel;
import java.io.File;
-import java.text.Collator;
import java.util.Comparator;
/**
* Plain java model for a sharing target activity.
*/
-class TargetActivity {
+public class TargetActivity {
private final int activityLabelResId;
private final Uri iconUri;
@@ -56,19 +56,6 @@ public boolean equals(Object o) {
}
TargetActivity that = (TargetActivity) o;
-
- if (activityLabelResId != that.activityLabelResId) {
- return false;
- }
- if (isMail != that.isMail) {
- return false;
- }
- if (lastSelection != that.lastSelection) {
- return false;
- }
- if (!iconUri.equals(that.iconUri)) {
- return false;
- }
return resolveInfo.equals(that.resolveInfo);
}
@@ -76,9 +63,6 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
int result = activityLabelResId;
- result = 31 * result + iconUri.hashCode();
- result = 31 * result + (isMail ? 1 : 0);
- result = 31 * result + (int) (lastSelection ^ (lastSelection >>> 32));
result = 31 * result + resolveInfo.hashCode();
return result;
}
@@ -140,12 +124,22 @@ public boolean isMailClient() {
return this.isMail;
}
+ /**
+ * Return a timestamp of the last selection inside the sharing dialog from you application.
+ *
+ * @return timestamp of the last selection in milliseconds since January 1, 1970 00:00:00.0 UTC
+ * or 0 if the target activity has never been selected by the user.
+ */
+ public long getLastSelection() {
+ return lastSelection;
+ }
+
/**
* Retrieve the label of the target activity.
*
* @return return target activity label or null if not yet loaded.
*/
- public CharSequence getLabel() {
+ CharSequence getLabel() {
return label;
}
@@ -169,42 +163,85 @@ void setLabel(CharSequence label) {
/**
* Comparator used to sort {@link TargetActivity} based on the recency of their previous
- * selection and their name as fallback when they have never been selected.
+ * selection and their default order as fallback when they have never been selected.
*
* The ordering imposed by this comparator on a set of {@link TargetActivity}
* is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean
* value as e1.equals(e2).
*/
- public static final class RecencyComparator implements Comparator {
+ public static final class RecencyComparatorProvider implements TargetActivityComparatorProvider {
+
+ /**
+ * Parcelable.
+ */
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public RecencyComparatorProvider createFromParcel(Parcel source) {
+ return new RecencyComparatorProvider(source);
+ }
- private final Collator mCollator = Collator.getInstance();
+ @Override
+ public RecencyComparatorProvider[] newArray(int size) {
+ return new RecencyComparatorProvider[size];
+ }
+ };
/**
* Comparator used to sort {@link TargetActivity} based on the recency of their previous
- * selection and their name as fallback when they have never been selected.
+ * selection and their default order as fallback when they have never been selected.
*
* The ordering imposed by this comparator on a set of {@link TargetActivity}
* is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean
* value as e1.equals(e2).
*/
- public RecencyComparator() {
- mCollator.setStrength(Collator.PRIMARY);
+ public RecencyComparatorProvider() {
+
}
+ /**
+ * Comparator used to sort {@link TargetActivity} based on the recency of their previous
+ * selection and their default order as fallback when they have never been selected.
+ *
+ * The ordering imposed by this comparator on a set of {@link TargetActivity}
+ * is not consistent with equals since c.compare(e1, e2)==0 has not the same boolean
+ * value as e1.equals(e2).
+ *
+ * @param in parcel.
+ */
+ protected RecencyComparatorProvider(Parcel in) {
+
+ }
+
+
@Override
- public int compare(TargetActivity lhs, TargetActivity rhs) {
- float lhsScore = lhs.lastSelection;
- float rhsScore = rhs.lastSelection;
-
- if (lhsScore > 0 && rhsScore > 0) {
- return (int) (rhsScore - lhsScore);
- } else if (lhsScore > 0) {
- return -1;
- } else if (rhsScore > 0) {
- return 1;
- } else {
- return 0;
- }
+ public Comparator provideComparator() {
+ return new Comparator() {
+ @Override
+ public int compare(TargetActivity lhs, TargetActivity rhs) {
+ float lhsScore = lhs.lastSelection;
+ float rhsScore = rhs.lastSelection;
+
+ if (lhsScore > 0 && rhsScore > 0) {
+ return (int) (rhsScore - lhsScore);
+ } else if (lhsScore > 0) {
+ return -1;
+ } else if (rhsScore > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ };
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+
}
}
}
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityAdapter.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityAdapter.java
index 47928a3..c2a20ea 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityAdapter.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityAdapter.java
@@ -1,5 +1,6 @@
package fr.tvbarthel.intentshare;
+import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
@@ -15,6 +16,7 @@ class TargetActivityAdapter extends RecyclerView.Adapter provideComparator();
+}
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityHeaderView.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityHeaderView.java
index 5f9d4d9..3ffb0ca 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityHeaderView.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityHeaderView.java
@@ -66,7 +66,7 @@ public void setModel(String label) {
}
/**
- * Initiliaze internal component
+ * Initialize internal component
*
* @param context holding context.
*/
@@ -78,7 +78,7 @@ private void initialize(Context context) {
)
);
Resources resources = context.getResources();
- height = resources.getDimensionPixelSize(R.dimen.isl_target_activity_view_height);
+ height = resources.getDimensionPixelSize(R.dimen.isl_target_activity_header_view_height);
setTextSize(
TypedValue.COMPLEX_UNIT_PX,
resources.getDimensionPixelSize(R.dimen.isl_target_activity_header_view_font_size)
@@ -92,6 +92,6 @@ private void initialize(Context context) {
setSingleLine(true);
setEllipsize(TextUtils.TruncateAt.END);
int padding = resources.getDimensionPixelSize(R.dimen.isl_default_padding);
- setPadding(padding, padding, padding, padding);
+ setPadding(getPaddingLeft(), padding, getPaddingRight(), padding);
}
}
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java
index f86cc11..9bf390c 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityManager.java
@@ -13,6 +13,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
/**
@@ -55,10 +56,12 @@ public TargetActivityManager() {
* Basically, resolve the list of {@link android.app.Activity} which can handled
* {@link Intent#ACTION_SEND}.
*
- * @param context context used to resolves target activities.
- * @param listener listener used to catch resolving events.
+ * @param context context used to resolves target activities.
+ * @param listener listener used to catch resolving events.
+ * @param comparator comparator used to sort the resolved target activities.
*/
- public void resolveTargetActivities(Context context, ResolveListener listener) {
+ public void resolveTargetActivities(Context context, ResolveListener listener,
+ Comparator comparator) {
targetActivities.clear();
sharedPreferences = context.getSharedPreferences(SHARED_PREF_KEY, Context.MODE_PRIVATE);
@@ -91,7 +94,7 @@ public void resolveTargetActivities(Context context, ResolveListener listener) {
}
}
- Collections.sort(targetActivities, new TargetActivity.RecencyComparator());
+ Collections.sort(targetActivities, comparator);
for (int i = 0; i < targetActivities.size(); i++) {
new AsyncLabelLoader(context, targetActivities.get(i), listener).execute();
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java
index 5519651..b639c9d 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetActivityView.java
@@ -115,8 +115,9 @@ private void initialize(Context context) {
height = resources.getDimensionPixelSize(R.dimen.isl_target_activity_view_height);
- int padding = resources.getDimensionPixelSize(R.dimen.isl_default_padding);
- setPadding(padding, padding, padding, padding);
+ int paddingVertical = resources.getDimensionPixelSize(R.dimen.isl_target_activity_padding_vertical);
+ int paddingHorizontal = resources.getDimensionPixelSize(R.dimen.isl_target_activity_padding_horizontal);
+ setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
setForeground(
ContextCompat.getDrawable(
@@ -125,13 +126,6 @@ private void initialize(Context context) {
)
);
- setBackgroundColor(
- ContextCompat.getColor(
- context,
- R.color.isl_target_activity_view_background
- )
- );
-
icon = ((ImageView) findViewById(R.id.target_activity_view_icon));
label = ((TextView) findViewById(R.id.target_activity_view_label));
diff --git a/library/src/main/java/fr/tvbarthel/intentshare/TargetChooserActivity.java b/library/src/main/java/fr/tvbarthel/intentshare/TargetChooserActivity.java
index dda6155..26af63c 100644
--- a/library/src/main/java/fr/tvbarthel/intentshare/TargetChooserActivity.java
+++ b/library/src/main/java/fr/tvbarthel/intentshare/TargetChooserActivity.java
@@ -9,7 +9,6 @@
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewTreeObserver;
@@ -122,6 +121,17 @@ public class TargetChooserActivity extends AppCompatActivity
*/
private Interpolator outInterpolator;
+ /**
+ * View used as background since recycler view padding can't allow to used
+ * recycler background directly.
+ */
+ private View background;
+
+ /**
+ * Used to know if the activity state has been restored after a saved instance.
+ */
+ private boolean stateRestored;
+
/**
* Simple activity used to allow the user to choose a target activity for the sharing intent.
*
@@ -154,6 +164,7 @@ public void onCreate(Bundle savedInstanceState) {
recyclerView = ((RecyclerView) findViewById(R.id.activity_target_chooser_recycler_list));
stickyTitle = ((TargetActivityHeaderView) findViewById(R.id.activity_chooser_sticky_title));
stickyShadow = findViewById(R.id.activity_chooser_sticky_title_shadow);
+ background = findViewById(R.id.activity_target_chooser_background);
targetActivities = new ArrayList<>();
selectedTargetActivity = null;
@@ -165,11 +176,12 @@ public void onCreate(Bundle savedInstanceState) {
rootView.setOnClickListener(this);
rootView.setAlpha(0f);
+ stateRestored = savedInstanceState != null;
setUpRecyclerView(savedInstanceState);
setUpStickyTitle();
targetActivityManager = new TargetActivityManager();
- targetActivityManager.resolveTargetActivities(this, this);
+ targetActivityManager.resolveTargetActivities(this, this, intentShare.comparatorProvider.provideComparator());
inInterpolator = new DecelerateInterpolator();
outInterpolator = new AccelerateInterpolator();
@@ -189,7 +201,7 @@ protected void onSaveInstanceState(Bundle outState) {
@Override
protected void onDestroy() {
super.onDestroy();
- if (!listenerNotified) {
+ if (!listenerNotified && !isChangingConfigurations()) {
IntentShareListener.notifySharingCanceled(this);
}
}
@@ -199,7 +211,7 @@ public void finish() {
super.finish();
if (selectedTargetActivity != null) {
IntentShareListener.notifySharingCompleted(this, selectedTargetActivity.getPackageName());
- } else {
+ } else if (!isChangingConfigurations()) {
IntentShareListener.notifySharingCanceled(this);
}
listenerNotified = true;
@@ -230,13 +242,7 @@ public void onLabelResolved(TargetActivity targetActivity) {
private void setUpRecyclerView(Bundle savedInstance) {
- recyclerView.setLayoutManager(
- new LinearLayoutManager(
- this,
- LinearLayoutManager.VERTICAL,
- false
- )
- );
+ recyclerView.setLayoutManager(LayoutManagerFactory.buildLayoutManager(this));
targetActivities = new ArrayList<>();
adapter = new TargetActivityAdapter(
targetActivities,
@@ -247,6 +253,12 @@ private void setUpRecyclerView(Bundle savedInstance) {
targetActivityViewHeight = getResources().getDimensionPixelSize(R.dimen.isl_target_activity_view_height);
+ if (savedInstance != null) {
+ currentRecyclerScrollY = savedInstance.getInt(SAVED_CURRENT_SCROLL_Y, 0);
+ } else {
+ currentRecyclerScrollY = 0;
+ }
+
recyclerView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@@ -257,28 +269,37 @@ public boolean onPreDraw() {
int maxStartingHeight = (int) (recyclerView.getHeight() / 2.5f);
int startingHeight = Math.min(totalHeight, maxStartingHeight);
recyclerPaddingTop = recyclerView.getHeight() - startingHeight;
- recyclerView.setPadding(0, recyclerPaddingTop, 0, 0);
+ recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerPaddingTop,
+ recyclerView.getPaddingRight(), 0);
recyclerView.setTranslationY(recyclerView.getHeight());
+ int backgroundTranslationY = Math.max(0, recyclerPaddingTop - currentRecyclerScrollY);
+ background.setTranslationY(recyclerView.getHeight() + backgroundTranslationY);
recyclerView.setAdapter(adapter);
- rootView.animate()
- .alpha(1f)
- .setDuration(animationDuration)
- .setInterpolator(inInterpolator)
- .setListener(null);
- recyclerView.animate()
- .translationY(0)
- .setDuration(animationDuration)
- .setInterpolator(inInterpolator)
- .setListener(null);
+ if (stateRestored) {
+ rootView.setAlpha(1f);
+ recyclerView.setTranslationY(0);
+ background.setTranslationY(backgroundTranslationY);
+ } else {
+ rootView.animate()
+ .alpha(1f)
+ .setDuration(animationDuration)
+ .setInterpolator(inInterpolator)
+ .setListener(null);
+ recyclerView.animate()
+ .translationY(0)
+ .setDuration(animationDuration)
+ .setInterpolator(inInterpolator)
+ .setListener(null);
+ background.animate()
+ .translationY(backgroundTranslationY)
+ .setDuration(animationDuration)
+ .setInterpolator(inInterpolator)
+ .setListener(null);
+ }
return false;
}
}
);
- if (savedInstance != null) {
- currentRecyclerScrollY = savedInstance.getInt(SAVED_CURRENT_SCROLL_Y, 0);
- } else {
- currentRecyclerScrollY = 0;
- }
recyclerView.addOnScrollListener(
new RecyclerView.OnScrollListener() {
@Override
@@ -289,10 +310,14 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
isStickyTitleDisplayed = true;
stickyTitle.setVisibility(View.VISIBLE);
stickyShadow.setVisibility(View.VISIBLE);
- } else if (isStickyTitleDisplayed && currentRecyclerScrollY < recyclerPaddingTop) {
- isStickyTitleDisplayed = false;
- stickyTitle.setVisibility(View.INVISIBLE);
- stickyShadow.setVisibility(View.INVISIBLE);
+ } else if (currentRecyclerScrollY < recyclerPaddingTop) {
+ if (isStickyTitleDisplayed) {
+ isStickyTitleDisplayed = false;
+ stickyTitle.setVisibility(View.INVISIBLE);
+ stickyShadow.setVisibility(View.INVISIBLE);
+ }
+ background.setTranslationY(recyclerPaddingTop - currentRecyclerScrollY);
+
}
}
}
@@ -325,6 +350,11 @@ public void onAnimationEnd(Animator animation) {
.setDuration(animationDuration)
.setInterpolator(outInterpolator)
.setListener(null);
+ background.animate()
+ .translationY(background.getTranslationY() + rootView.getHeight())
+ .setDuration(animationDuration)
+ .setInterpolator(outInterpolator)
+ .setListener(null);
stickyShadow.animate()
.translationY(rootView.getHeight())
.setDuration(animationDuration)
diff --git a/library/src/main/res/layout-v23/isl_target_activity_view.xml b/library/src/main/res/layout-v23/isl_target_activity_view.xml
new file mode 100644
index 0000000..6436e1f
--- /dev/null
+++ b/library/src/main/res/layout-v23/isl_target_activity_view.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/library/src/main/res/layout/isl_activity_target_chooser.xml b/library/src/main/res/layout/isl_activity_target_chooser.xml
index e7c4ccb..ed88933 100644
--- a/library/src/main/res/layout/isl_activity_target_chooser.xml
+++ b/library/src/main/res/layout/isl_activity_target_chooser.xml
@@ -6,23 +6,33 @@
android:background="@color/isl_activity_translucent_background"
android:fitsSystemWindows="true">
+
+
+ android:overScrollMode="never"
+ android:paddingLeft="@dimen/isl_target_activity_recycler_padding"
+ android:paddingRight="@dimen/isl_target_activity_recycler_padding" />
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/isl_default_padding"
+ android:paddingRight="@dimen/isl_default_padding" />
diff --git a/library/src/main/res/layout/isl_target_activity_view.xml b/library/src/main/res/layout/isl_target_activity_view.xml
index d01e53d..c9bc933 100644
--- a/library/src/main/res/layout/isl_target_activity_view.xml
+++ b/library/src/main/res/layout/isl_target_activity_view.xml
@@ -15,10 +15,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
- android:layout_marginLeft="@dimen/isl_target_activity_view_label_margin_left"
+ android:layout_marginLeft="@dimen/isl_target_activity_view_label_icon_margin"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/isl_target_activity_view_label"
- android:textSize="19sp"/>
+ android:textSize="@dimen/isl_target_activity_view_text_size"/>
\ No newline at end of file
diff --git a/library/src/main/res/values-v23/dimens.xml b/library/src/main/res/values-v23/dimens.xml
new file mode 100644
index 0000000..8a16867
--- /dev/null
+++ b/library/src/main/res/values-v23/dimens.xml
@@ -0,0 +1,17 @@
+
+
+ 16dp
+
+
+ 16dp
+ 4dp
+ 48dp
+ 0dp
+ 56dp
+ 19sp
+ 60dp
+ 120dp
+ 12sp
+ @dimen/isl_default_padding
+ 0dp
+
\ No newline at end of file
diff --git a/library/src/main/res/values/dimens.xml b/library/src/main/res/values/dimens.xml
index d4d354d..1bc34d1 100644
--- a/library/src/main/res/values/dimens.xml
+++ b/library/src/main/res/values/dimens.xml
@@ -3,10 +3,15 @@
16dp
+ 16dp
+ 16dp
24dp
10dp
- 54dp
+ 54dp
19sp
+ 60dp
60dp
-
+ 19sp
+ 0dp
+ @dimen/isl_default_padding
\ No newline at end of file
diff --git a/sample/build.gradle b/sample/build.gradle
index e9a6e4e..4ae107b 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -8,8 +8,8 @@ android {
applicationId "fr.tvbarthel.intentsharesample"
minSdkVersion 16
targetSdkVersion 23
- versionCode 2
- versionName "1.1"
+ versionCode 3
+ versionName "1.2"
}
buildTypes {
release {
diff --git a/sample/src/main/java/fr/tvbarthel/intentsharesample/Adapter.java b/sample/src/main/java/fr/tvbarthel/intentsharesample/Adapter.java
index bbffab8..d3d90e4 100644
--- a/sample/src/main/java/fr/tvbarthel/intentsharesample/Adapter.java
+++ b/sample/src/main/java/fr/tvbarthel/intentsharesample/Adapter.java
@@ -1,7 +1,6 @@
package fr.tvbarthel.intentsharesample;
import android.support.v7.widget.RecyclerView;
-import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -96,9 +95,6 @@ public void onAddExtraProviderRequested() {
public void onExtraProviderDetailRequested(ExtraProviderWrapper wrapper) {
if (listener != null) {
int wrapperPosition = Adapter.this.extraProviders.indexOf(wrapper);
- if (wrapperPosition == -1) {
- Log.e("LARGONNE", "wrapper position -1 : " + wrapper);
- }
listener.onExtraProviderDetailRequested(wrapperPosition, wrapper);
}
}
diff --git a/sample/src/main/java/fr/tvbarthel/intentsharesample/MainActivity.java b/sample/src/main/java/fr/tvbarthel/intentsharesample/MainActivity.java
index 506b6dd..4af81ef 100644
--- a/sample/src/main/java/fr/tvbarthel/intentsharesample/MainActivity.java
+++ b/sample/src/main/java/fr/tvbarthel/intentsharesample/MainActivity.java
@@ -26,6 +26,7 @@
import fr.tvbarthel.intentshare.IconLoader;
import fr.tvbarthel.intentshare.IntentShare;
import fr.tvbarthel.intentshare.IntentShareListener;
+import fr.tvbarthel.intentshare.TargetActivityComparatorProvider;
import fr.tvbarthel.intentshare.loader.glide.GlideIconLoader;
import fr.tvbarthel.intentshare.loader.picasso.PicassoIconLoader;
@@ -49,6 +50,7 @@ public class MainActivity extends AppCompatActivity implements
private PicassoIconLoader picassoIconLoader;
private IconLoader iconLoader;
+ private TargetActivityComparatorProvider customComparatorProvider;
private GlideIconLoader glideIconLoader;
private String targetPackage;
@@ -68,6 +70,7 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
targetPackage = null;
+ customComparatorProvider = null;
intentShareListener = new IntentShareListener() {
@Override
@@ -120,6 +123,12 @@ public boolean onOptionsItemSelected(MenuItem item) {
}
iconLoader = picassoIconLoader;
break;
+ case R.id.sorting_default:
+ customComparatorProvider = null;
+ break;
+ case R.id.sorting_custom:
+ customComparatorProvider = new SocialTargetActivityComparatorProvider();
+ break;
default:
return super.onOptionsItemSelected(item);
@@ -200,6 +209,9 @@ public void onClick(View v) {
.facebookBody(facebookLink)
.twitterBody(tweet)
.listener(intentShareListener);
+ if (customComparatorProvider != null) {
+ intentShare.comparatorProvider(customComparatorProvider);
+ }
if (iconLoader != null) {
intentShare.iconLoader(iconLoader);
}
diff --git a/sample/src/main/java/fr/tvbarthel/intentsharesample/SocialTargetActivityComparatorProvider.java b/sample/src/main/java/fr/tvbarthel/intentsharesample/SocialTargetActivityComparatorProvider.java
new file mode 100644
index 0000000..b6f8fbc
--- /dev/null
+++ b/sample/src/main/java/fr/tvbarthel/intentsharesample/SocialTargetActivityComparatorProvider.java
@@ -0,0 +1,105 @@
+package fr.tvbarthel.intentsharesample;
+
+import android.os.Parcel;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+
+import fr.tvbarthel.intentshare.TargetActivity;
+import fr.tvbarthel.intentshare.TargetActivityComparatorProvider;
+
+/**
+ * Simple custom {@link TargetActivityComparatorProvider} used to illustrate how to provide
+ * a different sorting for the target activities displayed to the user.
+ *
+ * This example simply displayed some social media apps at first and then keep the original
+ * order returned by the system.
+ */
+class SocialTargetActivityComparatorProvider implements TargetActivityComparatorProvider {
+
+ private ArrayList prioritizedPackageNames;
+
+ /**
+ * Parcelable.
+ */
+ public static final Creator CREATOR
+ = new Creator() {
+ @Override
+ public SocialTargetActivityComparatorProvider createFromParcel(Parcel source) {
+ return new SocialTargetActivityComparatorProvider(source);
+ }
+
+ @Override
+ public SocialTargetActivityComparatorProvider[] newArray(int size) {
+ return new SocialTargetActivityComparatorProvider[size];
+ }
+ };
+
+ /**
+ * Simple custom {@link TargetActivityComparatorProvider} used to illustrate how to provide
+ * a different sorting for the target activities displayed to the user.
+ *
+ * This example simply displayed some social media apps at first and then keep the original
+ * order returned by the system.
+ */
+ public SocialTargetActivityComparatorProvider() {
+ prioritizedPackageNames = new ArrayList<>();
+ prioritizedPackageNames.add("com.instagram.android"); // instagram
+ prioritizedPackageNames.add("com.snapchat.android"); // snapchat
+ prioritizedPackageNames.add("com.pinterest"); // pinterest
+ prioritizedPackageNames.add("com.sgiggle.production"); // tango
+ prioritizedPackageNames.add("jom.tencent.mm"); // wechat
+ prioritizedPackageNames.add("jp.naver.line.android"); // line
+ prioritizedPackageNames.add("com.whatsapp"); // what's app
+ prioritizedPackageNames.add("com.google.android.talk"); // hangout
+ prioritizedPackageNames.add("com.google.android.apps.plus"); // G+
+ prioritizedPackageNames.add("com.twitter.android"); // twitter
+ prioritizedPackageNames.add("com.facebook.orca"); // FB
+ prioritizedPackageNames.add("com.facebook.katana"); // FB
+ }
+
+ /**
+ * Simple custom {@link TargetActivityComparatorProvider} used to illustrate how to provide
+ * a different sorting for the target activities displayed to the user.
+ *
+ * This example simply displayed some social media apps at first and then keep the original
+ * order returned by the system.
+ *
+ * @param in parcel.
+ */
+ protected SocialTargetActivityComparatorProvider(Parcel in) {
+ prioritizedPackageNames = new ArrayList<>();
+ in.readStringList(prioritizedPackageNames);
+ }
+
+
+ @Override
+ public Comparator provideComparator() {
+ return new Comparator() {
+ @Override
+ public int compare(TargetActivity lhs, TargetActivity rhs) {
+ int lhsPriority = prioritizedPackageNames.indexOf(lhs.getPackageName());
+ int rhsPriority = prioritizedPackageNames.indexOf(rhs.getPackageName());
+ if (lhsPriority != -1 && rhsPriority != -1) {
+ return lhsPriority - rhsPriority;
+ } else if (lhsPriority != -1) {
+ return -1;
+ } else if (rhsPriority != -1) {
+ return 1;
+ } else {
+ return 0; // keep the original order if not present in the prioritized list.
+ }
+ }
+ };
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeStringList(prioritizedPackageNames);
+ }
+}
diff --git a/sample/src/main/res/menu/activity_sample_menu.xml b/sample/src/main/res/menu/activity_sample_menu.xml
index debd6f7..44590ff 100644
--- a/sample/src/main/res/menu/activity_sample_menu.xml
+++ b/sample/src/main/res/menu/activity_sample_menu.xml
@@ -1,15 +1,36 @@
\ No newline at end of file
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
index 3e59c7f..7620beb 100644
--- a/sample/src/main/res/values/strings.xml
+++ b/sample/src/main/res/values/strings.xml
@@ -3,6 +3,8 @@
Default IconLoader
Picasso IconLoader
Glide IconLoader
+ Default Sorting (recency)
+ Custom Sorting (social first)
Improves the sharing experience on Android with IntentShare.
http://tvbarthel.github.io/IntentShare/
@@ -32,4 +34,6 @@
Mail subject
Mail body
Default provider
+ Target sorting
+ Icon loading