/* * Copyright (C) 2020 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. */ package android.widget; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.content.ClipData; import android.content.ClipDescription; import android.view.View; import android.view.inputmethod.InputConnection; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Set; /** * Callback for apps to implement handling for insertion of rich content. "Rich content" here refers * to both text and non-text content: plain text, styled text, HTML, images, videos, audio files, * etc. * *
This callback can be attached to different types of UI components. For editable * {@link TextView} components, implementations should typically wrap * {@link TextView#DEFAULT_RICH_CONTENT_RECEIVER}. * *
Example implementation:
*
* public class MyRichContentReceiver implements RichContentReceiver<TextView> {
*
* private static final Set<String> SUPPORTED_MIME_TYPES = Collections.unmodifiableSet(
* Set.of("text/*", "image/gif", "image/png", "image/jpg"));
*
* @NonNull
* @Override
* public Set<String> getSupportedMimeTypes() {
* return SUPPORTED_MIME_TYPES;
* }
*
* @Override
* public boolean onReceive(@NonNull TextView textView, @NonNull ClipData clip,
* int source, int flags) {
* if (clip.getDescription().hasMimeType("image/*")) {
* return receiveImage(textView, clip);
* }
* return TextView.DEFAULT_RICH_CONTENT_RECEIVER.onReceive(textView, clip, source);
* }
*
* private boolean receiveImage(@NonNull TextView textView, @NonNull ClipData clip) {
* // ... app-specific logic to handle the content URI in the clip ...
* }
* }
*
*
* @param For editable {@link TextView} components, this function will be invoked for the * following scenarios: *
For text, if the view has a selection, the selection should be overwritten by the * clip; if there's no selection, this method should insert the content at the current * cursor position. * *
For rich content (e.g. an image), this function may insert the content inline, or it may * add the content as an attachment (could potentially go into a completely separate view). * *
This function may be invoked with a clip whose MIME type is not in the list of supported * types returned by {@link #getSupportedMimeTypes()}. This provides the opportunity to * implement custom fallback logic if desired. * * @param view The view where the content insertion was requested. * @param clip The clip to insert. * @param source The trigger of the operation. * @param flags Optional flags to configure the insertion behavior. Use 0 for default * behavior. See {@code FLAG_} constants on this interface for other options. * @return Returns true if the clip was inserted. */ boolean onReceive(@NonNull T view, @NonNull ClipData clip, @Source int source, int flags); /** * Returns the MIME types that can be handled by this callback. * *
Different platform features (e.g. pasting from the clipboard, inserting stickers from the
* keyboard, etc) may use this function to conditionally alter their behavior. For example, the
* keyboard may choose to hide its UI for inserting GIFs if the input field that has focus has
* a {@link RichContentReceiver} set and the MIME types returned from this function don't
* include "image/gif".
*
* @return An immutable set with the MIME types supported by this callback. The returned
* MIME types may contain wildcards such as "text/*", "image/*", etc.
*/
@NonNull
Set