如何为自定义 Android 视图实现提取文本

2024-02-25

背景

Android 中的自定义编辑器视图能够通过系统键盘接收文本InputConnection。我已经能够成功地做出这样的观点。然而,当设备处于横向模式时,系统有时会选择显示提取的文本视图。当用户在此模式下键入时,提取的文本视图应使用自定义视图中的相同文本进行更新。

我无法实现提取的文本视图功能。 (这是我尝试过的一些事情。 https://stackoverflow.com/questions/50829361/how-to-update-extracted-text-in-a-custom-editor-view)

我也无法找到任何清晰的文档或完整的示例来说明如何做到这一点。 (以下是我读过的一些更好的东西:one https://developer.android.com/guide/topics/text/creating-input-method, two https://developer.android.com/reference/android/view/inputmethod/InputConnection, three https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/java/android/widget/TextView.java, four https://android.googlesource.com/platform/frameworks/base/+/37960c7/core/java/android/widget/Editor.java).

MCVE

我已经尽可能创建了最基本的自定义编辑器。下面的 gif 显示了该功能。它可以从键盘接收文本,但不会更新横向提取的文本视图。因此,除非关闭键盘,否则您无法看到更新的文本。

MyCustomView.java

public class MyCustomView extends View {

    SpannableStringBuilder mText;
    Paint mPaint;

    public MyCustomView(Context context) {
        this(context, null, 0);
    }

    public MyCustomView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setFocusableInTouchMode(true);
        mText = new SpannableStringBuilder();
        mPaint = new Paint();
        mPaint.setColor(Color.BLACK);
        mPaint.setTextSize(60);
        mPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText(mText, 0, mText.length(), 50, 100, mPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            if (imm == null) return false;
            imm.showSoftInput(this, InputMethodManager.SHOW_FORCED);
        }
        return true;
    }

    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
        return new MyInputConnection(this, true);
    }
}

MyInputConnection.java

public class MyInputConnection extends BaseInputConnection {

    private MyCustomView customView;

    MyInputConnection(View targetView, boolean fullEditor) {
        super(targetView, fullEditor);
        customView = (MyCustomView) targetView;
    }

    @Override
    public Editable getEditable() {
        return customView.mText;
    }

    @Override
    public boolean commitText(CharSequence text, int newCursorPosition) {
        boolean returnValue = super.commitText(text, newCursorPosition);
        customView.invalidate();
        return returnValue;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

活动主文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <net.example.extractedtext.MyCustomView
        android:id="@+id/myCustomView"
        android:background="@android:color/holo_blue_bright"
        android:layout_margin="50dp"
        android:layout_width="300dp"
        android:layout_height="150dp"
        android:layout_centerHorizontal="true"
        />

</RelativeLayout>

Summary

我正在寻找一个规范的答案,它描述并给出了如何为自定义编辑器视图实现提取的文本更新的示例。

如果我自己弄清楚,我会添加我自己的答案。在那之前我能做到的最好的就是完全禁用提取的文本 https://stackoverflow.com/a/4726646/3681880。这并不理想。


您可以使用inputMethodManager.updateExtractedText(view, token, extractedText)为了那个原因。

这个方法的第一个参数很简单。您可以传递您的实例自定义视图那里。最后一张也。只需创建提取文本并像这样设置其字段。

ExtractedText extractedText = new ExtractedText();
extractedText.text = "sample text";

更难的是正确通过token。要了解此参数的正确值,您可以覆盖方法getExtractedText(ExtractedTextRequest request, int flags)在你的里面我的输入连接类(令牌存储在请求对象中)。

@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
        currentToken = request.token;
        return new ExtractedText();
}

我空空返回提取文本此方法中的对象使视图处于活动状态(默认情况下文本看起来像提示)。

您可以在这里找到我的解决方案https://github.com/ljarka/ExtractedText https://github.com/ljarka/ExtractedText

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为自定义 Android 视图实现提取文本 的相关文章

随机推荐