Inflate dismissal background instead of drawing while swiping
- Only swipe the foreground out to have the background revealed. - Inflate dismissal_swipe_background.xml while swiping. - Fix the fly-in transition. - Fix the overlapping problem. Bug: 129742618 Test: robotests Change-Id: I5311e50332d0ea0437d1693d075d5c3a2176a443
This commit is contained in:
		
							
								
								
									
										46
									
								
								res/layout/dismissal_swipe_background.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								res/layout/dismissal_swipe_background.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!--
 | 
			
		||||
  Copyright (C) 2019 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
<LinearLayout
 | 
			
		||||
    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:id="@+id/dismissal_swipe_background"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="match_parent"
 | 
			
		||||
    android:background="@color/homepage_card_dismissal_background">
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:id="@+id/dismissal_icon_start"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:src="@drawable/ic_delete"
 | 
			
		||||
        android:layout_gravity="start|center_vertical"
 | 
			
		||||
        android:layout_marginStart="@dimen/homepage_card_dismissal_side_margin"/>
 | 
			
		||||
 | 
			
		||||
    <Space
 | 
			
		||||
        android:layout_width="0dp"
 | 
			
		||||
        android:layout_height="0dp"
 | 
			
		||||
        android:layout_weight="1"/>
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:id="@+id/dismissal_icon_end"
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:src="@drawable/ic_delete"
 | 
			
		||||
        android:layout_gravity="end|center_vertical"
 | 
			
		||||
        android:layout_marginEnd="@dimen/homepage_card_dismissal_side_margin"/>
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
@@ -21,41 +21,49 @@
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    style="@style/ContextualCardStyle">
 | 
			
		||||
 | 
			
		||||
    <ViewFlipper
 | 
			
		||||
        android:id="@+id/view_flipper"
 | 
			
		||||
    <FrameLayout
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
        <LinearLayout
 | 
			
		||||
            android:id="@+id/content"
 | 
			
		||||
        <include layout="@layout/dismissal_swipe_background"/>
 | 
			
		||||
 | 
			
		||||
        <ViewFlipper
 | 
			
		||||
            android:id="@+id/view_flipper"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="match_parent"
 | 
			
		||||
            android:paddingEnd="@dimen/homepage_card_padding_end"
 | 
			
		||||
            android:paddingTop="@dimen/homepage_half_card_padding_top"
 | 
			
		||||
            android:paddingBottom="@dimen/homepage_half_card_padding_bottom"
 | 
			
		||||
            android:orientation="vertical">
 | 
			
		||||
            android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
            <ImageView
 | 
			
		||||
                android:id="@android:id/icon"
 | 
			
		||||
                android:layout_width="@dimen/homepage_card_icon_size"
 | 
			
		||||
                android:layout_height="@dimen/homepage_card_icon_size"
 | 
			
		||||
                android:layout_marginStart="@dimen/homepage_card_icon_padding_start"/>
 | 
			
		||||
 | 
			
		||||
            <TextView
 | 
			
		||||
                android:id="@android:id/title"
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/content"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:maxLines="2"
 | 
			
		||||
                android:minLines="1"
 | 
			
		||||
                android:ellipsize="end"
 | 
			
		||||
                android:layout_marginStart="@dimen/homepage_card_text_padding_start"
 | 
			
		||||
                android:layout_marginTop="@dimen/homepage_half_card_title_margin_top"
 | 
			
		||||
                android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
 | 
			
		||||
                android:layout_height="match_parent"
 | 
			
		||||
                android:paddingEnd="@dimen/homepage_card_padding_end"
 | 
			
		||||
                android:paddingTop="@dimen/homepage_half_card_padding_top"
 | 
			
		||||
                android:paddingBottom="@dimen/homepage_half_card_padding_bottom"
 | 
			
		||||
                android:background="@color/contextual_card_background"
 | 
			
		||||
                android:orientation="vertical">
 | 
			
		||||
 | 
			
		||||
        </LinearLayout>
 | 
			
		||||
                <ImageView
 | 
			
		||||
                    android:id="@android:id/icon"
 | 
			
		||||
                    android:layout_width="@dimen/homepage_card_icon_size"
 | 
			
		||||
                    android:layout_height="@dimen/homepage_card_icon_size"
 | 
			
		||||
                    android:layout_marginStart="@dimen/homepage_card_icon_padding_start"/>
 | 
			
		||||
 | 
			
		||||
        <!--dismissal view-->
 | 
			
		||||
        <include layout="@layout/homepage_dismissal_view"/>
 | 
			
		||||
                <TextView
 | 
			
		||||
                    android:id="@android:id/title"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:maxLines="2"
 | 
			
		||||
                    android:minLines="1"
 | 
			
		||||
                    android:ellipsize="end"
 | 
			
		||||
                    android:layout_marginStart="@dimen/homepage_card_text_padding_start"
 | 
			
		||||
                    android:layout_marginTop="@dimen/homepage_half_card_title_margin_top"
 | 
			
		||||
                    android:textAppearance="@style/TextAppearance.ConditionCardTitle"/>
 | 
			
		||||
 | 
			
		||||
    </ViewFlipper>
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
 | 
			
		||||
            <!--dismissal view-->
 | 
			
		||||
            <include layout="@layout/homepage_dismissal_view"/>
 | 
			
		||||
 | 
			
		||||
        </ViewFlipper>
 | 
			
		||||
    </FrameLayout>
 | 
			
		||||
</com.google.android.material.card.MaterialCardView>
 | 
			
		||||
@@ -21,21 +21,35 @@
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    style="@style/ContextualCardStyle">
 | 
			
		||||
 | 
			
		||||
    <ViewFlipper
 | 
			
		||||
        android:id="@+id/view_flipper"
 | 
			
		||||
    <FrameLayout
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="wrap_content">
 | 
			
		||||
        android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
        <androidx.slice.widget.SliceView
 | 
			
		||||
            android:id="@+id/slice_view"
 | 
			
		||||
        <include layout="@layout/dismissal_swipe_background"/>
 | 
			
		||||
 | 
			
		||||
        <ViewFlipper
 | 
			
		||||
            android:id="@+id/view_flipper"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_gravity="center_vertical"
 | 
			
		||||
            android:importantForAccessibility="no"
 | 
			
		||||
            style="@style/SliceViewStyle"/>
 | 
			
		||||
            android:layout_height="wrap_content">
 | 
			
		||||
 | 
			
		||||
        <!--dismissal view-->
 | 
			
		||||
        <include layout="@layout/homepage_dismissal_view"/>
 | 
			
		||||
            <LinearLayout
 | 
			
		||||
                android:id="@+id/slice_view_wrapper"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="match_parent"
 | 
			
		||||
                android:background="@color/contextual_card_background">
 | 
			
		||||
 | 
			
		||||
    </ViewFlipper>
 | 
			
		||||
                <androidx.slice.widget.SliceView
 | 
			
		||||
                    android:id="@+id/slice_view"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_gravity="center_vertical"
 | 
			
		||||
                    android:importantForAccessibility="no"
 | 
			
		||||
                    style="@style/SliceViewStyle"/>
 | 
			
		||||
            </LinearLayout>
 | 
			
		||||
 | 
			
		||||
            <!--dismissal view-->
 | 
			
		||||
            <include layout="@layout/homepage_dismissal_view"/>
 | 
			
		||||
 | 
			
		||||
        </ViewFlipper>
 | 
			
		||||
    </FrameLayout>
 | 
			
		||||
</com.google.android.material.card.MaterialCardView>
 | 
			
		||||
@@ -492,6 +492,7 @@
 | 
			
		||||
        <item name="android:paddingEnd">8dp</item>
 | 
			
		||||
 | 
			
		||||
        <item name="rowStyle">@style/SliceRowStyle</item>
 | 
			
		||||
        <item name="android:background">@color/contextual_card_background</item>
 | 
			
		||||
    </style>
 | 
			
		||||
 | 
			
		||||
    <style name="SliceRowStyle">
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ package com.android.settings.homepage.contextualcards.slices;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.LinearLayout;
 | 
			
		||||
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView;
 | 
			
		||||
import androidx.slice.Slice;
 | 
			
		||||
@@ -70,10 +71,12 @@ class SliceFullCardRendererHelper {
 | 
			
		||||
 | 
			
		||||
    static class SliceViewHolder extends RecyclerView.ViewHolder {
 | 
			
		||||
        public final SliceView sliceView;
 | 
			
		||||
        public final LinearLayout sliceViewWrapper;
 | 
			
		||||
 | 
			
		||||
        public SliceViewHolder(View view) {
 | 
			
		||||
            super(view);
 | 
			
		||||
            sliceView = view.findViewById(R.id.slice_view);
 | 
			
		||||
            sliceViewWrapper = view.findViewById(R.id.slice_view_wrapper);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,6 @@ package com.android.settings.homepage.contextualcards.slices;
 | 
			
		||||
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.graphics.Canvas;
 | 
			
		||||
import android.graphics.Paint;
 | 
			
		||||
import android.graphics.RectF;
 | 
			
		||||
import android.graphics.drawable.Drawable;
 | 
			
		||||
import android.view.View;
 | 
			
		||||
import android.widget.ViewFlipper;
 | 
			
		||||
 | 
			
		||||
@@ -41,18 +38,10 @@ public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
 | 
			
		||||
 | 
			
		||||
    private final Context mContext;
 | 
			
		||||
    private final SwipeDismissalDelegate.Listener mListener;
 | 
			
		||||
    private final Drawable mIconDelete;
 | 
			
		||||
    private final Paint mBgPaint;
 | 
			
		||||
    private final int mBgCornerRadius;
 | 
			
		||||
 | 
			
		||||
    public SwipeDismissalDelegate(Context context, SwipeDismissalDelegate.Listener listener) {
 | 
			
		||||
        mContext = context;
 | 
			
		||||
        mListener = listener;
 | 
			
		||||
        mIconDelete = mContext.getDrawable(R.drawable.ic_delete);
 | 
			
		||||
        mBgPaint = new Paint();
 | 
			
		||||
        mBgPaint.setColor(mContext.getColor(R.color.homepage_card_dismissal_background));
 | 
			
		||||
        mBgCornerRadius = mContext.getResources()
 | 
			
		||||
                .getDimensionPixelSize(R.dimen.homepage_card_corner_radius);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -100,41 +89,49 @@ public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
 | 
			
		||||
        mListener.onSwiped(viewHolder.getAdapterPosition());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void clearView(@NonNull RecyclerView recyclerView,
 | 
			
		||||
            @NonNull RecyclerView.ViewHolder viewHolder) {
 | 
			
		||||
        final View view = getSwipeableView(viewHolder);
 | 
			
		||||
        getDefaultUIUtil().clearView(view);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView,
 | 
			
		||||
            @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
 | 
			
		||||
            boolean isCurrentlyActive) {
 | 
			
		||||
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
 | 
			
		||||
        final View view = getSwipeableView(viewHolder);
 | 
			
		||||
        final View iconStart = viewHolder.itemView.findViewById(R.id.dismissal_icon_start);
 | 
			
		||||
        final View iconEnd = viewHolder.itemView.findViewById(R.id.dismissal_icon_end);
 | 
			
		||||
 | 
			
		||||
        final View itemView = viewHolder.itemView;
 | 
			
		||||
        final int iconMargin = mContext.getResources()
 | 
			
		||||
                .getDimensionPixelSize(R.dimen.homepage_card_dismissal_side_margin);
 | 
			
		||||
        final int iconTop =
 | 
			
		||||
                itemView.getTop() + (itemView.getHeight() - mIconDelete.getIntrinsicHeight()) / 2;
 | 
			
		||||
        final int iconBottom = iconTop + mIconDelete.getIntrinsicHeight();
 | 
			
		||||
 | 
			
		||||
        if (dX > 0) { //swipe to the right
 | 
			
		||||
            final int iconLeft = itemView.getLeft() + iconMargin;
 | 
			
		||||
            final int iconRight = iconLeft + mIconDelete.getIntrinsicWidth();
 | 
			
		||||
            final RectF rect = new RectF(itemView.getLeft(), itemView.getTop(),
 | 
			
		||||
                    itemView.getLeft() + ((int) dX) + mBgCornerRadius, itemView.getBottom());
 | 
			
		||||
            mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
 | 
			
		||||
            c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
 | 
			
		||||
        if (dX > 0) {
 | 
			
		||||
            iconStart.setVisibility(View.VISIBLE);
 | 
			
		||||
            iconEnd.setVisibility(View.GONE);
 | 
			
		||||
        } else if (dX < 0) {
 | 
			
		||||
            final int iconRight = itemView.getRight() - iconMargin;
 | 
			
		||||
            final int iconLeft = iconRight - mIconDelete.getIntrinsicWidth();
 | 
			
		||||
            final RectF rect = new RectF(itemView.getRight() + ((int) dX), itemView.getTop(),
 | 
			
		||||
                    itemView.getRight(), itemView.getBottom());
 | 
			
		||||
            mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
 | 
			
		||||
            c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
 | 
			
		||||
            iconStart.setVisibility(View.GONE);
 | 
			
		||||
            iconEnd.setVisibility(View.VISIBLE);
 | 
			
		||||
        }
 | 
			
		||||
        mIconDelete.draw(c);
 | 
			
		||||
        getDefaultUIUtil().onDraw(c, recyclerView, view, dX, dY, actionState, isCurrentlyActive);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int getInitialViewId(RecyclerView.ViewHolder viewHolder) {
 | 
			
		||||
        if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
 | 
			
		||||
            return R.id.content;
 | 
			
		||||
        }
 | 
			
		||||
        return R.id.slice_view;
 | 
			
		||||
        return R.id.slice_view_wrapper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the foreground view from the {@link android.widget.FrameLayout} as we only swipe
 | 
			
		||||
     * the foreground out in {@link SwipeDismissalDelegate#onChildDraw} and gets the view
 | 
			
		||||
     * beneath revealed.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The foreground view.
 | 
			
		||||
     */
 | 
			
		||||
    private View getSwipeableView(RecyclerView.ViewHolder viewHolder) {
 | 
			
		||||
        if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
 | 
			
		||||
            return ((SliceHalfCardRendererHelper.HalfCardViewHolder) viewHolder).content;
 | 
			
		||||
        }
 | 
			
		||||
        return ((SliceFullCardRendererHelper.SliceViewHolder) viewHolder).sliceViewWrapper;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -149,7 +149,7 @@ public class SliceContextualCardRendererTest {
 | 
			
		||||
 | 
			
		||||
        btnKeep.performClick();
 | 
			
		||||
 | 
			
		||||
        assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
 | 
			
		||||
        assertThat(viewFlipper.getCurrentView().getId()).isEqualTo(R.id.slice_view_wrapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -204,7 +204,7 @@ public class SliceContextualCardRendererTest {
 | 
			
		||||
 | 
			
		||||
        mRenderer.onStop();
 | 
			
		||||
 | 
			
		||||
        assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
 | 
			
		||||
        assertThat(viewFlipper.getCurrentView().getId()).isEqualTo(R.id.slice_view_wrapper);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private RecyclerView.ViewHolder getSliceViewHolder() {
 | 
			
		||||
 
 | 
			
		||||
@@ -99,9 +99,9 @@ public class SwipeDismissalDelegateTest {
 | 
			
		||||
        final RecyclerView.ViewHolder holder = getSliceViewHolder();
 | 
			
		||||
        final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
 | 
			
		||||
        viewFlipper.setDisplayedChild(0);
 | 
			
		||||
        final View sliceView = holder.itemView.findViewById(R.id.slice_view);
 | 
			
		||||
        final View sliceViewWrapper = holder.itemView.findViewById(R.id.slice_view_wrapper);
 | 
			
		||||
 | 
			
		||||
        assertThat(viewFlipper.getCurrentView()).isEqualTo(sliceView);
 | 
			
		||||
        assertThat(viewFlipper.getCurrentView()).isEqualTo(sliceViewWrapper);
 | 
			
		||||
        assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getSliceViewHolder()))
 | 
			
		||||
                .isNotEqualTo(0);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user