[go: nahoru, domu]

Use setCustomSelectionActionModeCallback

Change Ib2348aef79a5153a40ed3ff39712879316cecab7 adds a possibility for
developers to fix 66939160 in support library. The bug causes the menu
created on text selection for ACTION_PROCESS_TEXT not to work properly
for O and O_MR1 devices.

This CL updates support library TextView extension widgets to use the
bug fix introduced in the previous CL.

Note that the first version of this CL
(I56e4a33d8849b46dce6a4e8c657490f4683b549e) had to be reverted as it was
causing an infinite loop between TextViewCompat and AppCompatTextView
(actually any extension of TextView). Now we are always calling the
super implementation of setCustomSelectionActionModeCallback to avoid
this situation.

Bug: 68991560
Test: none
Change-Id: Ic7e7411c3e1fc5735290e9707cdcf6ac2dbb3746
diff --git a/compat/src/main/java/androidx/core/widget/TextViewCompat.java b/compat/src/main/java/androidx/core/widget/TextViewCompat.java
index 9fe6bb4..b7ffb3a 100644
--- a/compat/src/main/java/androidx/core/widget/TextViewCompat.java
+++ b/compat/src/main/java/androidx/core/widget/TextViewCompat.java
@@ -465,7 +465,7 @@
     /**
      * Sets a selection action mode callback on a TextView.
      *
-     * Also this method can be used to fix a bug in framework SDK 26. On these affected devices,
+     * Also this method can be used to fix a bug in framework SDK 26/27. On these affected devices,
      * the bug causes the menu containing the options for handling ACTION_PROCESS_TEXT after text
      * selection to miss a number of items. This method can be used to fix this wrong behaviour for
      * a text view, by passing any custom callback implementation. If no custom callback is desired,
@@ -486,16 +486,30 @@
      */
     public static void setCustomSelectionActionModeCallback(@NonNull final TextView textView,
                 @NonNull final ActionMode.Callback callback) {
-        if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27) {
-            textView.setCustomSelectionActionModeCallback(callback);
-            return;
-        }
+        textView.setCustomSelectionActionModeCallback(
+                wrapCustomSelectionActionModeCallback(textView, callback));
+    }
 
+    /**
+     * @see #setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    @NonNull
+    public static ActionMode.Callback wrapCustomSelectionActionModeCallback(
+            @NonNull final TextView textView,
+            @NonNull final ActionMode.Callback callback) {
+        if (Build.VERSION.SDK_INT < 26 || Build.VERSION.SDK_INT > 27
+                || callback instanceof OreoCallback) {
+            // If the bug does not affect the current SDK version, or if
+            // the callback was already wrapped, no need to wrap it.
+            return callback;
+        }
         // A bug in O and O_MR1 causes a number of options for handling the ACTION_PROCESS_TEXT
         // intent after selection to not be displayed in the menu, although they should be.
         // Here we fix this, by removing the menu items created by the framework code, and
         // adding them (and the missing ones) back correctly.
-        textView.setCustomSelectionActionModeCallback(new OreoCallback(callback, textView));
+        return new OreoCallback(callback, textView);
     }
 
     @TargetApi(26) // TODO was anonymous but https://issuetracker.google.com/issues/76458979
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiButton.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiButton.java
index 5367067..d1138d9 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiButton.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiButton.java
@@ -19,9 +19,11 @@
 import android.os.Build;
 import android.text.InputFilter;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.widget.Button;
 
 import androidx.annotation.RequiresApi;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * Button widget enhanced with emoji capability by using {@link EmojiTextViewHelper}. When used
@@ -81,4 +83,14 @@
         }
         return mEmojiTextViewHelper;
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiEditText.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiEditText.java
index 75b6440..765e82e 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiEditText.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiEditText.java
@@ -19,6 +19,7 @@
 import android.os.Build;
 import android.text.method.KeyListener;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.EditText;
@@ -26,6 +27,7 @@
 import androidx.annotation.IntRange;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
+import androidx.core.widget.TextViewCompat;
 import androidx.emoji.text.EmojiCompat;
 
 /**
@@ -122,4 +124,14 @@
         }
         return mEmojiEditTextHelper;
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiExtractEditText.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiExtractEditText.java
index 4c79c17..1279d71 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiExtractEditText.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiExtractEditText.java
@@ -23,13 +23,16 @@
 import android.os.Build;
 import android.text.method.KeyListener;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.widget.TextView;
 
 import androidx.annotation.IntRange;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.core.widget.TextViewCompat;
 import androidx.emoji.text.EmojiCompat;
 import androidx.emoji.text.EmojiSpan;
 
@@ -149,4 +152,14 @@
         }
         return mEmojiEditTextHelper;
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextView.java b/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextView.java
index 81e65a1..83802b9 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextView.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/EmojiTextView.java
@@ -19,9 +19,11 @@
 import android.os.Build;
 import android.text.InputFilter;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.widget.TextView;
 
 import androidx.annotation.RequiresApi;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * TextView widget enhanced with emoji capability by using {@link EmojiTextViewHelper}. When used
@@ -81,4 +83,14 @@
         }
         return mEmojiTextViewHelper;
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/emoji/core/src/main/java/androidx/emoji/widget/ExtractButtonCompat.java b/emoji/core/src/main/java/androidx/emoji/widget/ExtractButtonCompat.java
index 96b06c3..813585c 100644
--- a/emoji/core/src/main/java/androidx/emoji/widget/ExtractButtonCompat.java
+++ b/emoji/core/src/main/java/androidx/emoji/widget/ExtractButtonCompat.java
@@ -21,10 +21,12 @@
 import android.content.Context;
 import android.os.Build;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.widget.Button;
 
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * Support library implementation for ExtractButton. Used by {@link EmojiExtractViewHelper} while
@@ -59,4 +61,14 @@
     public boolean hasWindowFocus() {
         return isEnabled() && getVisibility() == VISIBLE ? true : false;
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java b/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java
index eda2de2..018f7dc1 100644
--- a/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java
+++ b/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java
@@ -20,12 +20,15 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.autofill.AutofillValue;
 import android.widget.EditText;
 import android.widget.TextView;
 
+import androidx.core.widget.TextViewCompat;
+
 /**
  * A custom EditText that satisfies the IME key monitoring requirements of GuidedStepFragment.
  */
@@ -138,4 +141,14 @@
             mAutofillListener.onAutofill(this);
         }
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/leanback/src/main/java/androidx/leanback/widget/ResizingTextView.java b/leanback/src/main/java/androidx/leanback/widget/ResizingTextView.java
index c2e916c..e7c9bf5 100644
--- a/leanback/src/main/java/androidx/leanback/widget/ResizingTextView.java
+++ b/leanback/src/main/java/androidx/leanback/widget/ResizingTextView.java
@@ -18,8 +18,10 @@
 import android.text.Layout;
 import android.util.AttributeSet;
 import android.util.TypedValue;
+import android.view.ActionMode;
 import android.widget.TextView;
 
+import androidx.core.widget.TextViewCompat;
 import androidx.leanback.R;
 
 /**
@@ -271,4 +273,14 @@
             setPadding(getPaddingLeft(), paddingTop, getPaddingRight(), paddingBottom);
         }
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/leanback/src/main/java/androidx/leanback/widget/RowHeaderView.java b/leanback/src/main/java/androidx/leanback/widget/RowHeaderView.java
index 4677e71..7ca6b2c 100644
--- a/leanback/src/main/java/androidx/leanback/widget/RowHeaderView.java
+++ b/leanback/src/main/java/androidx/leanback/widget/RowHeaderView.java
@@ -15,8 +15,10 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.widget.TextView;
 
+import androidx.core.widget.TextViewCompat;
 import androidx.leanback.R;
 
 /**
@@ -36,4 +38,14 @@
         super(context, attrs, defStyle);
     }
 
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
+
 }
diff --git a/leanback/src/main/java/androidx/leanback/widget/SearchEditText.java b/leanback/src/main/java/androidx/leanback/widget/SearchEditText.java
index 6531f1d..a9b29f1 100644
--- a/leanback/src/main/java/androidx/leanback/widget/SearchEditText.java
+++ b/leanback/src/main/java/androidx/leanback/widget/SearchEditText.java
@@ -18,6 +18,7 @@
 import android.util.Log;
 import android.view.KeyEvent;
 
+import androidx.core.widget.TextViewCompat;
 import androidx.leanback.R;
 
 /**
diff --git a/leanback/src/main/java/androidx/leanback/widget/StreamingTextView.java b/leanback/src/main/java/androidx/leanback/widget/StreamingTextView.java
index 75c629f..b41d663 100644
--- a/leanback/src/main/java/androidx/leanback/widget/StreamingTextView.java
+++ b/leanback/src/main/java/androidx/leanback/widget/StreamingTextView.java
@@ -27,10 +27,13 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Property;
+import android.view.ActionMode;
 import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.EditText;
+import android.widget.TextView;
 
+import androidx.core.widget.TextViewCompat;
 import androidx.leanback.R;
 
 import java.util.List;
@@ -291,4 +294,14 @@
     }
 
     public void updateRecognizedText(String stableText, List<Float> rmsValues) {}
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/slices/view/src/main/java/androidx/slice/widget/RemoteInputView.java b/slices/view/src/main/java/androidx/slice/widget/RemoteInputView.java
index d4ff299..3a77498 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RemoteInputView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RemoteInputView.java
@@ -29,6 +29,7 @@
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.ActionMode;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -50,6 +51,7 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.core.content.ContextCompat;
+import androidx.core.widget.TextViewCompat;
 import androidx.slice.SliceItem;
 import androidx.slice.view.R;
 
@@ -415,6 +417,17 @@
             }
 
         }
+
+        /**
+         * See
+         * {@link TextViewCompat
+         * #setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+         */
+        @Override
+        public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+            super.setCustomSelectionActionModeCallback(TextViewCompat
+                    .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+        }
     }
 
     /** Whether key will, by default, trigger a click on the focused view.
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatAutoCompleteTextView.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatAutoCompleteTextView.java
index 3bfe8ae..febd7cb 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatAutoCompleteTextView.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatAutoCompleteTextView.java
@@ -23,9 +23,11 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.AutoCompleteTextView;
+import android.widget.TextView;
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.Nullable;
@@ -33,6 +35,7 @@
 import androidx.appcompat.R;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.core.view.TintableBackgroundView;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * A {@link AutoCompleteTextView} which supports compatible features on older versions of the
@@ -186,4 +189,14 @@
         return AppCompatHintHelper.onCreateInputConnection(super.onCreateInputConnection(outAttrs),
                 outAttrs, this);
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java
index 42bed17..98425bf 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatButton.java
@@ -23,6 +23,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.Button;
@@ -357,4 +358,14 @@
             mTextHelper.setAllCaps(allCaps);
         }
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatCheckedTextView.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatCheckedTextView.java
index 2491a5f..52772b3 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatCheckedTextView.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatCheckedTextView.java
@@ -18,12 +18,14 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.CheckedTextView;
 
 import androidx.annotation.DrawableRes;
 import androidx.appcompat.content.res.AppCompatResources;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * A {@link CheckedTextView} which supports compatible features on older versions of the platform.
@@ -88,4 +90,14 @@
         return AppCompatHintHelper.onCreateInputConnection(super.onCreateInputConnection(outAttrs),
                 outAttrs, this);
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java
index b188094..c8afbba 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatEditText.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.Drawable;
 import android.text.Editable;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.EditText;
@@ -34,6 +35,7 @@
 import androidx.appcompat.R;
 import androidx.core.os.BuildCompat;
 import androidx.core.view.TintableBackgroundView;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * A {@link EditText} which supports compatible features on older versions of the platform,
@@ -184,4 +186,14 @@
         return AppCompatHintHelper.onCreateInputConnection(super.onCreateInputConnection(outAttrs),
                 outAttrs, this);
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java
index fc4620f..f8b38f6 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/AppCompatTextView.java
@@ -23,6 +23,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.ActionMode;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.widget.TextView;
@@ -408,4 +409,14 @@
     public void setLineHeight(@Px @IntRange(from = 0) int lineHeight) {
         TextViewCompat.setLineHeight(this, lineHeight);
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/DialogTitle.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/DialogTitle.java
index 40291a0..0dca18d2 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/DialogTitle.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/DialogTitle.java
@@ -23,10 +23,12 @@
 import android.text.Layout;
 import android.util.AttributeSet;
 import android.util.TypedValue;
+import android.view.ActionMode;
 import android.widget.TextView;
 
 import androidx.annotation.RestrictTo;
 import androidx.appcompat.R;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * Used by dialogs to change the font size and number of lines to try to fit
@@ -79,4 +81,14 @@
             }
         }
     }
+
+    /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
 }
\ No newline at end of file
diff --git a/v7/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java b/v7/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java
index cc511ee..4a0ade4 100644
--- a/v7/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java
+++ b/v7/appcompat/src/main/java/androidx/appcompat/widget/SwitchCompat.java
@@ -35,6 +35,7 @@
 import android.text.method.TransformationMethod;
 import android.util.AttributeSet;
 import android.util.Property;
+import android.view.ActionMode;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
@@ -43,6 +44,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.CompoundButton;
+import android.widget.TextView;
 
 import androidx.annotation.Nullable;
 import androidx.appcompat.R;
@@ -50,6 +52,7 @@
 import androidx.appcompat.text.AllCapsTransformationMethod;
 import androidx.core.graphics.drawable.DrawableCompat;
 import androidx.core.view.ViewCompat;
+import androidx.core.widget.TextViewCompat;
 
 /**
  * SwitchCompat is a version of the Switch widget which on devices back to API v7. It does not
@@ -1407,6 +1410,16 @@
     }
 
     /**
+     * See
+     * {@link TextViewCompat#setCustomSelectionActionModeCallback(TextView, ActionMode.Callback)}
+     */
+    @Override
+    public void setCustomSelectionActionModeCallback(ActionMode.Callback actionModeCallback) {
+        super.setCustomSelectionActionModeCallback(TextViewCompat
+                .wrapCustomSelectionActionModeCallback(this, actionModeCallback));
+    }
+
+    /**
      * Taken from android.util.MathUtils
      */
     private static float constrain(float amount, float low, float high) {