mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 15:26:58 +00:00
Better estimate the height of widget recycler view
Test: Expand and collapse apps in the widgets picker. Then, observe
the height of the fast scroller is correctly displayed.
Bug: 181629430
Change-Id: I9efcf902f8548fc5c8a398609758d43123228e5e
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:paddingVertical="20dp"
|
||||
android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
|
||||
@@ -108,6 +108,8 @@
|
||||
<dimen name="widget_cell_vertical_padding">8dp</dimen>
|
||||
<dimen name="widget_cell_horizontal_padding">16dp</dimen>
|
||||
|
||||
<dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
|
||||
|
||||
<dimen name="widget_preview_shadow_blur">0.5dp</dimen>
|
||||
<dimen name="widget_preview_key_shadow_distance">1dp</dimen>
|
||||
<dimen name="widget_preview_corner_radius">2dp</dimen>
|
||||
|
||||
@@ -385,14 +385,16 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
|
||||
@Override
|
||||
public int getHeaderViewHeight() {
|
||||
// No need to check work profile here because mInitialTabHeight is always 0 if there is no
|
||||
// work profile.
|
||||
return mInitialTabsHeight
|
||||
+ measureHeightWithVerticalMargins(mSearchAndRecommendationViewHolder.mContainer);
|
||||
return measureHeightWithVerticalMargins(mSearchAndRecommendationViewHolder.mCollapseHandle)
|
||||
+ measureHeightWithVerticalMargins(mSearchAndRecommendationViewHolder.mHeaderTitle)
|
||||
+ measureHeightWithVerticalMargins(mSearchAndRecommendationViewHolder.mSearchBar);
|
||||
}
|
||||
|
||||
/** private the height, in pixel, + the vertical margins of a given view. */
|
||||
private static int measureHeightWithVerticalMargins(View view) {
|
||||
if (view.getVisibility() != VISIBLE) {
|
||||
return 0;
|
||||
}
|
||||
MarginLayoutParams marginLayoutParams = (MarginLayoutParams) view.getLayoutParams();
|
||||
return view.getMeasuredHeight() + marginLayoutParams.bottomMargin
|
||||
+ marginLayoutParams.topMargin;
|
||||
|
||||
@@ -122,6 +122,11 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
return mVisibleEntries.size();
|
||||
}
|
||||
|
||||
/** Returns all items that will be drawn in a recycler view. */
|
||||
public List<WidgetsListBaseEntry> getItems() {
|
||||
return mVisibleEntries;
|
||||
}
|
||||
|
||||
/** Gets the section name for {@link com.android.launcher3.views.RecyclerViewFastScroller}. */
|
||||
public String getSectionName(int pos) {
|
||||
return mVisibleEntries.get(pos).mTitleSectionName;
|
||||
|
||||
@@ -21,13 +21,19 @@ import android.graphics.Point;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.TableLayout;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
|
||||
|
||||
import com.android.launcher3.BaseRecyclerView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListContentEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
|
||||
/**
|
||||
* The widgets recycler view.
|
||||
@@ -39,8 +45,10 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
||||
private final int mScrollbarTop;
|
||||
|
||||
private final Point mFastScrollerOffset = new Point();
|
||||
private final int mEstimatedWidgetListHeaderHeight;
|
||||
private boolean mTouchDownOnScroller;
|
||||
private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider;
|
||||
private int mLastVisibleWidgetContentTableHeight = 0;
|
||||
|
||||
public WidgetsRecyclerView(Context context) {
|
||||
this(context, null);
|
||||
@@ -55,6 +63,12 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
||||
super(context, attrs, defStyleAttr);
|
||||
mScrollbarTop = getResources().getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
|
||||
addOnItemTouchListener(this);
|
||||
|
||||
ActivityContext activity = ActivityContext.lookupContext(getContext());
|
||||
DeviceProfile grid = activity.getDeviceProfile();
|
||||
mEstimatedWidgetListHeaderHeight = grid.iconSizePx
|
||||
+ 2 * context.getResources().getDimensionPixelSize(
|
||||
R.dimen.widget_list_header_view_vertical_padding);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,21 +137,32 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
||||
|
||||
View child = getChildAt(0);
|
||||
int rowIndex = getChildPosition(child);
|
||||
int y = (child.getMeasuredHeight() * rowIndex);
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view instanceof TableLayout) {
|
||||
// This assumes there is ever only one content shown in this recycler view.
|
||||
mLastVisibleWidgetContentTableHeight = view.getMeasuredHeight();
|
||||
}
|
||||
}
|
||||
|
||||
int scrollPosition = getItemsHeight(rowIndex);
|
||||
int offset = getLayoutManager().getDecoratedTop(child);
|
||||
|
||||
return getPaddingTop() + y - offset;
|
||||
return getPaddingTop() + scrollPosition - offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available scroll height:
|
||||
* AvailableScrollHeight = Total height of the all items - last page height
|
||||
* Returns the available scroll height, in pixel.
|
||||
*
|
||||
* <p>If the recycler view can't be scrolled, returns 0.
|
||||
*/
|
||||
@Override
|
||||
protected int getAvailableScrollHeight() {
|
||||
View child = getChildAt(0);
|
||||
return child.getMeasuredHeight() * mAdapter.getItemCount() + getScrollBarTop()
|
||||
+ getPaddingBottom() - mScrollbar.getHeight();
|
||||
// AvailableScrollHeight = Total height of the all items - first page height
|
||||
int firstPageHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
|
||||
int totalHeightOfAllItems = getItemsHeight(/* untilIndex= */ mAdapter.getItemCount());
|
||||
int availableScrollHeight = totalHeightOfAllItems - firstPageHeight;
|
||||
return Math.max(0, availableScrollHeight);
|
||||
}
|
||||
|
||||
private boolean isModelNotReady() {
|
||||
@@ -180,6 +205,31 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
||||
mHeaderViewDimensionsProvider = headerViewDimensionsProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of the height, in pixels, of this list adapter's items from index 0 until
|
||||
* {@code untilIndex}.
|
||||
*
|
||||
* <p>If the untilIndex is larger than the total number of items in this adapter, returns the
|
||||
* sum of all items' height.
|
||||
*/
|
||||
private int getItemsHeight(int untilIndex) {
|
||||
if (untilIndex > mAdapter.getItems().size()) {
|
||||
untilIndex = mAdapter.getItems().size();
|
||||
}
|
||||
int totalItemsHeight = 0;
|
||||
for (int i = 0; i < untilIndex; i++) {
|
||||
WidgetsListBaseEntry entry = mAdapter.getItems().get(i);
|
||||
if (entry instanceof WidgetsListHeaderEntry) {
|
||||
totalItemsHeight += mEstimatedWidgetListHeaderHeight;
|
||||
} else if (entry instanceof WidgetsListContentEntry) {
|
||||
totalItemsHeight += mLastVisibleWidgetContentTableHeight;
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Can't estimate height for " + entry);
|
||||
}
|
||||
}
|
||||
return totalItemsHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides dimensions of the header view that is shown at the top of a
|
||||
* {@link WidgetsRecyclerView}.
|
||||
|
||||
Reference in New Issue
Block a user