diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 1b805aced0dd7..8b510a448d2be 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -114,6 +114,7 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ImageUtils;
+import com.android.internal.widget.ResolverDrawerLayout;
import com.google.android.collect.Lists;
@@ -143,6 +144,8 @@ public class ChooserActivity extends ResolverActivity {
public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
= "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
+ private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
+
private static final boolean DEBUG = false;
/**
@@ -502,6 +505,21 @@ public class ChooserActivity extends ResolverActivity {
chooserHeader.setElevation(defaultElevation);
}
});
+
+ mResolverDrawerLayout.setOnCollapsedChangedListener(
+ new ResolverDrawerLayout.OnCollapsedChangedListener() {
+
+ // Only consider one expansion per activity creation
+ private boolean mWrittenOnce = false;
+
+ @Override
+ public void onCollapsedChanged(boolean isCollapsed) {
+ if (!isCollapsed && !mWrittenOnce) {
+ incrementNumSheetExpansions();
+ mWrittenOnce = true;
+ }
+ }
+ });
}
if (DEBUG) {
@@ -881,6 +899,15 @@ public class ChooserActivity extends ResolverActivity {
return CONTENT_PREVIEW_TEXT;
}
+ private int getNumSheetExpansions() {
+ return getPreferences(Context.MODE_PRIVATE).getInt(PREF_NUM_SHEET_EXPANSIONS, 0);
+ }
+
+ private void incrementNumSheetExpansions() {
+ getPreferences(Context.MODE_PRIVATE).edit().putInt(PREF_NUM_SHEET_EXPANSIONS,
+ getNumSheetExpansions() + 1).apply();
+ }
+
@Override
protected void onDestroy() {
super.onDestroy();
@@ -2494,19 +2521,25 @@ public class ChooserActivity extends ResolverActivity {
private DirectShareViewHolder mDirectShareViewHolder;
private int mChooserTargetWidth = 0;
+ private boolean mShowAzLabelIfPoss;
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
private static final int VIEW_TYPE_CONTENT_PREVIEW = 2;
private static final int VIEW_TYPE_PROFILE = 3;
+ private static final int VIEW_TYPE_AZ_LABEL = 4;
private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4;
private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8;
+ private static final int NUM_EXPANSIONS_TO_HIDE_AZ_LABEL = 20;
+
public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
mChooserListAdapter = wrappedAdapter;
mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
+ mShowAzLabelIfPoss = getNumSheetExpansions() < NUM_EXPANSIONS_TO_HIDE_AZ_LABEL;
+
wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
@@ -2559,6 +2592,7 @@ public class ChooserActivity extends ResolverActivity {
+ getProfileRowCount()
+ getServiceTargetRowCount()
+ getCallerAndRankedTargetRowCount()
+ + getAzLabelRowCount()
+ Math.ceil(
(float) mChooserListAdapter.getAlphaTargetCount()
/ getMaxTargetsPerRow())
@@ -2596,6 +2630,11 @@ public class ChooserActivity extends ResolverActivity {
return 0;
}
+ public int getAzLabelRowCount() {
+ // Only show a label if the a-z list is showing
+ return (mShowAzLabelIfPoss && mChooserListAdapter.getAlphaTargetCount() > 0) ? 1 : 0;
+ }
+
@Override
public Object getItem(int position) {
// We have nothing useful to return here.
@@ -2620,6 +2659,10 @@ public class ChooserActivity extends ResolverActivity {
return createProfileView(convertView, parent);
}
+ if (viewType == VIEW_TYPE_AZ_LABEL) {
+ return createAzLabelView(parent);
+ }
+
if (convertView == null) {
holder = createViewHolder(viewType, parent);
} else {
@@ -2633,27 +2676,29 @@ public class ChooserActivity extends ResolverActivity {
@Override
public int getItemViewType(int position) {
- if (position == 0 && getContentPreviewRowCount() == 1) {
- return VIEW_TYPE_CONTENT_PREVIEW;
- }
+ int count;
- if (getProfileRowCount() == 1 && position == getContentPreviewRowCount()) {
- return VIEW_TYPE_PROFILE;
- }
+ int countSum = (count = getContentPreviewRowCount());
+ if (count > 0 && position < countSum) return VIEW_TYPE_CONTENT_PREVIEW;
- final int start = getFirstRowPosition(position);
- final int startType = mChooserListAdapter.getPositionTargetType(start);
+ countSum += (count = getProfileRowCount());
+ if (count > 0 && position < countSum) return VIEW_TYPE_PROFILE;
- if (startType == ChooserListAdapter.TARGET_SERVICE) {
- return VIEW_TYPE_DIRECT_SHARE;
- }
+ countSum += (count = getServiceTargetRowCount());
+ if (count > 0 && position < countSum) return VIEW_TYPE_DIRECT_SHARE;
+
+ countSum += (count = getCallerAndRankedTargetRowCount());
+ if (count > 0 && position < countSum) return VIEW_TYPE_NORMAL;
+
+ countSum += (count = getAzLabelRowCount());
+ if (count > 0 && position < countSum) return VIEW_TYPE_AZ_LABEL;
return VIEW_TYPE_NORMAL;
}
@Override
public int getViewTypeCount() {
- return 4;
+ return 5;
}
private ViewGroup createContentPreviewView(View convertView, ViewGroup parent) {
@@ -2680,6 +2725,10 @@ public class ChooserActivity extends ResolverActivity {
return profileRow;
}
+ private View createAzLabelView(ViewGroup parent) {
+ return mLayoutInflater.inflate(R.layout.chooser_az_label_row, parent, false);
+ }
+
private RowViewHolder loadViewsIntoRow(RowViewHolder holder) {
final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int exactSpec = MeasureSpec.makeMeasureSpec(mChooserTargetWidth,
@@ -2778,16 +2827,24 @@ public class ChooserActivity extends ResolverActivity {
}
/**
- * Need to merge CALLER + ranked STANDARD into a single row. All other types
- * are placed into their own row as determined by their target type, and dividers
- * are added in the list to separate each type.
+ * Need to merge CALLER + ranked STANDARD into a single row and prevent a separator from
+ * showing on top of the AZ list if the AZ label is visible. All other types are placed into
+ * their own row as determined by their target type, and dividers are added in the list to
+ * separate each type.
*/
int getRowType(int rowPosition) {
+ // Merge caller and ranked standard into a single row
int positionType = mChooserListAdapter.getPositionTargetType(rowPosition);
if (positionType == ChooserListAdapter.TARGET_CALLER) {
return ChooserListAdapter.TARGET_STANDARD;
}
+ // If an the A-Z label is shown, prevent a separator from appearing by making the A-Z
+ // row type the same as the suggestion row type
+ if (getAzLabelRowCount() > 0 && positionType == ChooserListAdapter.TARGET_STANDARD_AZ) {
+ return ChooserListAdapter.TARGET_STANDARD;
+ }
+
return positionType;
}
@@ -2867,6 +2924,8 @@ public class ChooserActivity extends ResolverActivity {
return serviceCount + (row - serviceRows) * getMaxTargetsPerRow();
}
+ row -= getAzLabelRowCount();
+
return callerAndRankedCount + serviceCount
+ (row - callerAndRankedRows - serviceRows) * getMaxTargetsPerRow();
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 6b0d85ef0b95c..3adb36f5e54bf 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -104,6 +104,7 @@ public class ResolverDrawerLayout extends ViewGroup {
private OnDismissedListener mOnDismissedListener;
private RunOnDismissedListener mRunOnDismissedListener;
+ private OnCollapsedChangedListener mOnCollapsedChangedListener;
private boolean mDismissLocked;
@@ -267,6 +268,10 @@ public class ResolverDrawerLayout extends ViewGroup {
return mOnDismissedListener != null && !mDismissLocked;
}
+ public void setOnCollapsedChangedListener(OnCollapsedChangedListener listener) {
+ mOnCollapsedChangedListener = listener;
+ }
+
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
@@ -548,6 +553,10 @@ public class ResolverDrawerLayout extends ViewGroup {
if (mScrollIndicatorDrawable != null) {
setWillNotDraw(!isCollapsed);
}
+
+ if (mOnCollapsedChangedListener != null) {
+ mOnCollapsedChangedListener.onCollapsedChanged(isCollapsed);
+ }
}
void dispatchOnDismissed() {
@@ -1078,8 +1087,25 @@ public class ResolverDrawerLayout extends ViewGroup {
};
}
+ /**
+ * Listener for sheet dismissed events.
+ */
public interface OnDismissedListener {
- public void onDismissed();
+ /**
+ * Callback when the sheet is dismissed by the user.
+ */
+ void onDismissed();
+ }
+
+ /**
+ * Listener for sheet collapsed / expanded events.
+ */
+ public interface OnCollapsedChangedListener {
+ /**
+ * Callback when the sheet is either fully expanded or collapsed.
+ * @param isCollapsed true when collapsed, false when expanded.
+ */
+ void onCollapsedChanged(boolean isCollapsed);
}
private class RunOnDismissedListener implements Runnable {
diff --git a/core/res/res/layout/chooser_az_label_row.xml b/core/res/res/layout/chooser_az_label_row.xml
new file mode 100644
index 0000000000000..1b733fc907cc1
--- /dev/null
+++ b/core/res/res/layout/chooser_az_label_row.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ef834aa01a360..75fd3a0c04b74 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5373,4 +5373,7 @@
Direct share not available
+
+ Apps list
+
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bb560d324809f..fbe340ed61d35 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3771,4 +3771,6 @@
+
+