Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3267)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java

Issue 2703463002: [List UI Unification] Basic list unification for phones (Closed)
Patch Set: [List UI Unification] Basic list unification for phones Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
index c3666d32b26d5fed18ba16607a5ed86d46850fb5..75a6889e318187b0da96c4ad96d91eb8a97812b0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListLayout.java
@@ -7,12 +7,16 @@ package org.chromium.chrome.browser.widget.selection;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.support.annotation.VisibleForTesting;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.AdapterDataObserver;
+import android.support.v7.widget.RecyclerView.ItemAnimator;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.support.v7.widget.Toolbar.OnMenuItemClickListener;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -30,8 +34,11 @@ import org.chromium.chrome.browser.widget.displaystyle.DisplayStyleObserver;
import org.chromium.chrome.browser.widget.displaystyle.HorizontalDisplayStyle;
import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
import org.chromium.chrome.browser.widget.displaystyle.UiConfig.DisplayStyle;
+import org.chromium.chrome.browser.widget.selection.SelectionDelegate.SelectionObserver;
import org.chromium.ui.base.DeviceFormFactor;
+import java.util.List;
+
import javax.annotation.Nullable;
/**
@@ -43,15 +50,47 @@ import javax.annotation.Nullable;
*
* @param <E> The type of the selectable items this layout holds.
*/
-public class SelectableListLayout<E> extends RelativeLayout implements DisplayStyleObserver {
+public class SelectableListLayout<E>
+ extends RelativeLayout implements DisplayStyleObserver, SelectionObserver<E> {
+ /**
+ * @param res Resources used to retrieve drawables and dimensions.
+ * @return The default list item lateral margin size in pixels. This value should be used in
+ * {@link HorizontalDisplayStyle#REGULAR} to hide the lateral shadow and rounded edges
+ * on items that use the list_item* 9-patches as a background.
+ */
+ public static int getDefaultListItemLateralMarginPx(Resources res) {
+ if (sDefaultListItemLateralMarginPx == -1) {
+ Rect listItemShadow = new Rect();
+ ApiCompatibilityUtils.getDrawable(res, R.drawable.card_middle)
+ .getPadding(listItemShadow);
+ int cardCornerRadius = res.getDimensionPixelSize(R.dimen.list_item_corner_radius);
+
+ assert listItemShadow.left == listItemShadow.right;
+
+ // A negative margin is used in HorizontalDisplayStyle#REGULAR to hide the lateral
+ // shadow.
+ sDefaultListItemLateralMarginPx = -(listItemShadow.left + cardCornerRadius);
+ }
+
+ return sDefaultListItemLateralMarginPx;
+ }
+
private static final int WIDE_DISPLAY_MIN_PADDING_DP = 16;
+ private static int sDefaultListItemLateralMarginPx = -1;
+
private Adapter<RecyclerView.ViewHolder> mAdapter;
private ViewStub mToolbarStub;
private TextView mEmptyView;
private LoadingView mLoadingView;
private RecyclerView mRecyclerView;
+ private ItemAnimator mItemAnimator;
SelectableListToolbar<E> mToolbar;
+ private FadingShadowView mToolbarShadow;
+
+ private boolean mToolbarPermanentlyHidden;
+ private int mEmptyStringResId;
+ private int mSearchEmptyStringResId;
private UiConfig mUiConfig;
@@ -86,14 +125,6 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
}
};
- /**
- * Unlike ListView or GridView, RecyclerView does not provide default empty
- * view implementation. We need to check it ourselves.
- */
- private void updateEmptyViewVisibility() {
- mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
- }
-
public SelectableListLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -135,7 +166,16 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+
mRecyclerView.setHasFixedSize(true);
+ mRecyclerView.addOnScrollListener(new OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ setToolbarShadowVisibility();
+ }
+ });
+
+ mItemAnimator = mRecyclerView.getItemAnimator();
return mRecyclerView;
}
@@ -165,14 +205,6 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
int normalGroupResId, int selectedGroupResId,
@Nullable Integer normalBackgroundColorResId, boolean hideShadowOnLargeTablets,
@Nullable OnMenuItemClickListener listener) {
- FadingShadowView shadow = (FadingShadowView) findViewById(R.id.shadow);
- if (hideShadowOnLargeTablets && DeviceFormFactor.isLargeTablet(getContext())) {
- shadow.setVisibility(View.GONE);
- } else {
- shadow.init(ApiCompatibilityUtils.getColor(getResources(),
- R.color.toolbar_shadow_color), FadingShadow.POSITION_TOP);
- }
-
mToolbarStub.setLayoutResource(toolbarLayoutId);
@SuppressWarnings("unchecked")
SelectableListToolbar<E> toolbar = (SelectableListToolbar<E>) mToolbarStub.inflate();
@@ -184,6 +216,18 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
mToolbar.setOnMenuItemClickListener(listener);
}
+ mToolbarShadow = (FadingShadowView) findViewById(R.id.shadow);
+ if (hideShadowOnLargeTablets && DeviceFormFactor.isLargeTablet(getContext())) {
+ mToolbarPermanentlyHidden = true;
+ mToolbarShadow.setVisibility(View.GONE);
+ } else {
+ mToolbarShadow.init(
+ ApiCompatibilityUtils.getColor(getResources(), R.color.toolbar_shadow_color),
+ FadingShadow.POSITION_TOP);
+ delegate.addObserver(this);
+ setToolbarShadowVisibility();
+ }
+
return mToolbar;
}
@@ -192,26 +236,26 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
*
* @param emptyDrawable The Drawable to show when the selectable list is empty.
* @param emptyStringResId The string to show when the selectable list is empty.
+ * @param searchEmptyStringResId The string to show when the selectable list is empty during
+ * a search.
* @return The {@link TextView} displayed when the list is empty.
*/
- public TextView initializeEmptyView(Drawable emptyDrawable, int emptyStringResId) {
+ public TextView initializeEmptyView(
+ Drawable emptyDrawable, int emptyStringResId, int searchEmptyStringResId) {
+ mEmptyStringResId = emptyStringResId;
+ mSearchEmptyStringResId = searchEmptyStringResId;
+
mEmptyView.setCompoundDrawablesWithIntrinsicBounds(null, emptyDrawable, null, null);
- mEmptyView.setText(emptyStringResId);
+ mEmptyView.setText(mEmptyStringResId);
return mEmptyView;
}
/**
- * @param emptyStringResId The string to show when the selectable list is empty.
- */
- public void setEmptyViewText(int emptyStringResId) {
- mEmptyView.setText(emptyStringResId);
- }
-
- /**
* Called when the view that owns the SelectableListLayout is destroyed.
*/
public void onDestroyed() {
mAdapter.unregisterAdapterDataObserver(mAdapterObserver);
+ mToolbar.getSelectionDelegate().removeObserver(this);
}
/**
@@ -248,6 +292,29 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
padding, mRecyclerView.getPaddingBottom());
}
+ @Override
+ public void onSelectionStateChange(List<E> selectedItems) {
+ setToolbarShadowVisibility();
+ }
+
+ /**
+ * Called when a search is starting.
+ */
+ public void onStartSearch() {
+ mRecyclerView.setItemAnimator(null);
+ mToolbarShadow.setVisibility(View.VISIBLE);
+ mEmptyView.setText(mSearchEmptyStringResId);
+ }
+
+ /**
+ * Called when a search has ended.
+ */
+ public void onEndSearch() {
+ mRecyclerView.setItemAnimator(mItemAnimator);
+ setToolbarShadowVisibility();
+ mEmptyView.setText(mEmptyStringResId);
+ }
+
/**
* @param displayStyle The current display style..
* @param resources The {@link Resources} used to retrieve configuration and display metrics.
@@ -264,4 +331,25 @@ public class SelectableListLayout<E> extends RelativeLayout implements DisplaySt
}
return padding;
}
+
+ private void setToolbarShadowVisibility() {
+ if (mToolbarPermanentlyHidden || mToolbar == null || mRecyclerView == null) return;
+
+ boolean showShadow = mRecyclerView.computeVerticalScrollOffset() != 0
+ || mToolbar.isSearching() || mToolbar.getSelectionDelegate().isSelectionEnabled();
+ mToolbarShadow.setVisibility(showShadow ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Unlike ListView or GridView, RecyclerView does not provide default empty
+ * view implementation. We need to check it ourselves.
+ */
+ private void updateEmptyViewVisibility() {
+ mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
+ }
+
+ @VisibleForTesting
+ public View getToolbarShadowForTests() {
+ return mToolbarShadow;
+ }
}

Powered by Google App Engine
This is Rietveld 408576698