Gboard: включить вставку GIF на EditText
Я использую Gboard от Google в своем приложении, и когда я ввожу GIF из приложения клавиатуры в свой EditText
затем показывает тост
"Текстовое поле не поддерживает вставку GIF с клавиатуры"
Я искал об этом тысячу раз и не могу найти результат
Любая помощь будет оценена.
3 ответа
Поддержка изображения с клавиатуры
Пользователи часто хотят общаться с смайликами, стикерами и другими видами
содержание. В предыдущих версиях Android программные клавиатуры (также известные как ввод
редакторы методов или IME) могут отправлять в приложения только юникод-эмодзи. Для богатых
контент, приложения должны были либо создавать API-интерфейсы для конкретных приложений, которые не могут быть использованы в
другие приложения или использовать обходной путь, такой как отправка изображений через Easy Share Action или
Буфер обмена.
Как это устроено
Для вставки изображения с клавиатуры требуется участие как IME, так и приложения. Следующая последовательность описывает каждый шаг в процессе вставки изображения:
Когда пользователь нажимает на EditText, редактор отправляет список типов содержимого MIME, которые он принимает, в EditorInfo.contentMimeTypes.
IME читает список поддерживаемых типов и отображает содержимое на программной клавиатуре, которое может принять редактор.
Когда пользователь выбирает изображение, IME вызывает commitContent() и отправляет InputContentInfo в редактор. Вызов commitContent() аналогичен вызову commitText(), но для расширенного содержимого. InputContentInfo содержит URI, который идентифицирует контент в контент-провайдере. Затем ваше приложение может запросить разрешение и прочитать содержимое с URI.
Чтобы принимать расширенный контент из IME, приложения должны сообщать IME, какие типы контента им нужны.
принимает и указывает метод обратного вызова, который выполняется, когда содержимое
получено. В следующем примере показано, как создать EditText, который
принять PNG изображения:
EditText editText = new EditText(this) {
@Override
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
final InputConnection ic = super.onCreateInputConnection(editorInfo);
EditorInfoCompat.setContentMimeTypes(editorInfo,
new String [] {"image/png"});
final InputConnectionCompat.OnCommitContentListener callback =
new InputConnectionCompat.OnCommitContentListener() {
@Override
public boolean onCommitContent(InputContentInfoCompat inputContentInfo,
int flags, Bundle opts) {
// read and display inputContentInfo asynchronously
if (BuildCompat.isAtLeastNMR1() && (flags &
InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
try {
inputContentInfo.requestPermission();
}
catch (Exception e) {
return false; // return false if failed
}
}
// read and display inputContentInfo asynchronously.
// call inputContentInfo.releasePermission() as needed.
return true; // return true if succeeded
}
};
return InputConnectionCompat.createWrapper(ic, editorInfo, callback);
}
};
Вот полная ссылка на документацию
https://developer.android.com/guide/topics/text/image-keyboard.html
Добавление поддержки изображений в IME
IME, которые хотят отправлять в приложения расширенный контент, должны реализовывать API-интерфейс Commit Content, как показано ниже:
Override
onStartInput()
или жеonStartInputView()
и прочитайте список поддерживаемых типов контента из целевого редактора. В следующем фрагменте кода показано, как проверить, принимает ли целевой редактор изображения GIF.
@Override
public void onStartInputView(EditorInfo info, boolean restarting) {
String[] mimeTypes = EditorInfoCompat.getContentMimeTypes(editorInfo);
boolean gifSupported = false;
for (String mimeType : mimeTypes) {
if (ClipDescription.compareMimeTypes(mimeType, "image/gif")) {
gifSupported = true;
}
}
if (gifSupported) {
// the target editor supports GIFs. enable corresponding content
} else {
// the target editor does not support GIFs. disable corresponding content
}
}
Зафиксируйте содержимое в приложении, когда пользователи выбирают изображение. Избегайте звонков
commitContent()
когда есть какой-либо текст, потому что это может привести к тому, что редактор потеряет фокус. В следующем фрагменте кода показано, как зафиксировать изображение GIF.
/**
* Commits a GIF image
*
* @param contentUri Content URI of the GIF image to be sent
* @param imageDescription Description of the GIF image to be sent
*/
public static void commitGifImage(Uri contentUri, String imageDescription) {
InputContentInfoCompat inputContentInfo = new InputContentInfoCompat(
contentUri,
new ClipDescription(imageDescription, new String[]{"image/gif"}));
InputConnection inputConnection = getCurrentInputConnection();
EditorInfo editorInfo = getCurrentInputEditorInfo();
Int flags = 0;
if (android.os.Build.VERSION.SDK_INT >= 25) {
flags |= InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION;
}
InputConnectionCompat.commitContent(
inputConnection, editorInfo, inputContentInfo, flags, opts);
}
Вот полная документация
https://developer.android.com/guide/topics/text/image-keyboard.html
Я нашел решение ниже откуда-то. Надеюсь, это поможет всем наверняка.
import android.content.Context;
import android.os.Bundle;
import android.support.v13.view.inputmethod.EditorInfoCompat;
import android.support.v13.view.inputmethod.InputConnectionCompat;
import android.support.v13.view.inputmethod.InputContentInfoCompat;
import android.support.v4.os.BuildCompat;
import android.util.AttributeSet;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
public class MyEditText extends android.support.v7.widget.AppCompatEditText {
private String[] imgTypeString;
private KeyBoardInputCallbackListener keyBoardInputCallbackListener;
public MyEditText(Context context) {
super(context);
initView();
}
public MyEditText(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
imgTypeString = new String[]{"image/png",
"image/gif",
"image/jpeg",
"image/webp"};
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
final InputConnection ic = super.onCreateInputConnection(outAttrs);
EditorInfoCompat.setContentMimeTypes(outAttrs,
imgTypeString);
return InputConnectionCompat.createWrapper(ic, outAttrs, callback);
}
final InputConnectionCompat.OnCommitContentListener callback =
new InputConnectionCompat.OnCommitContentListener() {
@Override
public boolean onCommitContent(InputContentInfoCompat inputContentInfo,
int flags, Bundle opts) {
// read and display inputContentInfo asynchronously
if (BuildCompat.isAtLeastNMR1() && (flags &
InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
try {
inputContentInfo.requestPermission();
} catch (Exception e) {
return false; // return false if failed
}
}
boolean supported = false;
for (final String mimeType : imgTypeString) {
if (inputContentInfo.getDescription().hasMimeType(mimeType)) {
supported = true;
break;
}
}
if (!supported) {
return false;
}
if (keyBoardInputCallbackListener != null) {
keyBoardInputCallbackListener.onCommitContent(inputContentInfo, flags, opts);
}
return true; // return true if succeeded
}
};
public interface KeyBoardInputCallbackListener {
void onCommitContent(InputContentInfoCompat inputContentInfo,
int flags, Bundle opts);
}
public void setKeyBoardInputCallbackListener(KeyBoardInputCallbackListener keyBoardInputCallbackListener) {
this.keyBoardInputCallbackListener = keyBoardInputCallbackListener;
}
public String[] getImgTypeString() {
return imgTypeString;
}
public void setImgTypeString(String[] imgTypeString) {
this.imgTypeString = imgTypeString;
}
}
Если вы хотите EditText со встроенной функциональностью, посмотрите мою библиотеку RichContentEditText: https://github.com/GregoryConrad/RichContentEditText
Это безболезненно позволяет передавать богатый контент (изображения и другие файлы) в приложение из IME. Вот пример кода:
XML
<?xml version="1.0" encoding="utf-8"?>
<!-- Root layout can be anything. Just make sure to include xmlns:app line. -->
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- The RichContentEditText -->
<!-- Notice app:allowedMimeTypes="images"; it is what accepts certain mime types
(you can do this programmatically too) -->
<com.gsconrad.richcontentedittext.RichContentEditText
android:id="@+id/rich_content_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/rich_content_edit_text_hint"
android:inputType="text"
app:allowedMimeTypes="images" />
</android.support.constraint.ConstraintLayout>
Джава
// MainActivity.java
private void setupRichContentEditText() {
RichContentEditText editText = findViewById(R.id.rich_content_edit_text);
// The following line sets the listener that is called when rich content is received
editText.setOnRichContentListener(new RichContentEditText.OnRichContentListener() {
// Called when a keyboard sends rich content
@Override
public void onRichContent(Uri contentUri, ClipDescription description) {
if (description.getMimeTypeCount() > 0) {
final String fileExtension = MimeTypeMap.getSingleton()
.getExtensionFromMimeType(description.getMimeType(0));
final String filename = "filenameGoesHere." + fileExtension;
File richContentFile = new File(getFilesDir(), filename);
// See the library example app for an implementation of writeToFileFromContentUri
if (!writeToFileFromContentUri(richContentFile, contentUri)) {
// We are in the background right now, make sure to run this in the foreground
Toast.makeText(MainActivity.this,
R.string.rich_content_copy_failure, Toast.LENGTH_LONG).show();
} else {
// We are in the background right now, make sure to run this in the foreground
WebView displayView = findViewById(R.id.display_view);
displayView.loadUrl("file://" + richContentFile.getAbsolutePath());
}
}
}
});
}