1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.homepage.contextualcards.slices;
18 
19 import android.graphics.Canvas;
20 import android.view.View;
21 
22 import androidx.annotation.NonNull;
23 import androidx.recyclerview.widget.ItemTouchHelper;
24 import androidx.recyclerview.widget.RecyclerView;
25 
26 import com.android.settings.R;
27 import com.android.settings.homepage.contextualcards.ContextualCard;
28 
29 public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
30 
31     private static final String TAG = "SwipeDismissalDelegate";
32 
33     public interface Listener {
onSwiped(int position)34         void onSwiped(int position);
35     }
36 
37     private final SwipeDismissalDelegate.Listener mListener;
38 
SwipeDismissalDelegate(SwipeDismissalDelegate.Listener listener)39     public SwipeDismissalDelegate(SwipeDismissalDelegate.Listener listener) {
40         mListener = listener;
41     }
42 
43     /**
44      * Determine whether the ability to drag or swipe should be enabled or not.
45      *
46      * Only allow swipe on {@link ContextualCard} built with view type
47      * {@link SliceContextualCardRenderer#VIEW_TYPE_FULL_WIDTH} or
48      * {@link SliceContextualCardRenderer#VIEW_TYPE_HALF_WIDTH}.
49      *
50      * When the dismissal view is displayed, the swipe will also be disabled.
51      */
52     @Override
getMovementFlags(@onNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder)53     public int getMovementFlags(@NonNull RecyclerView recyclerView,
54             @NonNull RecyclerView.ViewHolder viewHolder) {
55         if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH
56                 || viewHolder.getItemViewType()
57                 == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {// Here we are making sure
58             // the current displayed view is the initial view of
59             // either slice full card or half card, and only allow swipe on these two types.
60             if (viewHolder.itemView.findViewById(R.id.dismissal_view).getVisibility()
61                     == View.VISIBLE) {
62                 // Disable swiping when we are in the dismissal view
63                 return 0;
64             }
65             return makeMovementFlags(0 /*dragFlags*/,
66                     ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT /*swipeFlags*/);
67         }
68         return 0;
69     }
70 
71     @Override
onMove(@onNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target)72     public boolean onMove(@NonNull RecyclerView recyclerView,
73             @NonNull RecyclerView.ViewHolder viewHolder,
74             @NonNull RecyclerView.ViewHolder target) {
75         return false;
76     }
77 
78     @Override
onSwiped(@onNull RecyclerView.ViewHolder viewHolder, int direction)79     public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
80         mListener.onSwiped(viewHolder.getAdapterPosition());
81     }
82 
83     @Override
clearView(@onNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder)84     public void clearView(@NonNull RecyclerView recyclerView,
85             @NonNull RecyclerView.ViewHolder viewHolder) {
86         final View view = getSwipeableView(viewHolder);
87         getDefaultUIUtil().clearView(view);
88     }
89 
90     @Override
onChildDraw(@onNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)91     public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView,
92             @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
93             boolean isCurrentlyActive) {
94         final View view = getSwipeableView(viewHolder);
95         final View iconStart = viewHolder.itemView.findViewById(R.id.dismissal_icon_start);
96         final View iconEnd = viewHolder.itemView.findViewById(R.id.dismissal_icon_end);
97 
98         if (dX > 0) {
99             iconStart.setVisibility(View.VISIBLE);
100             iconEnd.setVisibility(View.GONE);
101         } else if (dX < 0) {
102             iconStart.setVisibility(View.GONE);
103             iconEnd.setVisibility(View.VISIBLE);
104         }
105         getDefaultUIUtil().onDraw(c, recyclerView, view, dX, dY, actionState, isCurrentlyActive);
106     }
107 
108     /**
109      * Get the foreground view from the {@link android.widget.FrameLayout} as we only swipe
110      * the foreground out in {@link SwipeDismissalDelegate#onChildDraw} and gets the view
111      * beneath revealed.
112      *
113      * @return The foreground view.
114      */
getSwipeableView(RecyclerView.ViewHolder viewHolder)115     private View getSwipeableView(RecyclerView.ViewHolder viewHolder) {
116         if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
117             return ((SliceHalfCardRendererHelper.HalfCardViewHolder) viewHolder).content;
118         }
119         return ((SliceFullCardRendererHelper.SliceViewHolder) viewHolder).sliceView;
120     }
121 }