如何为自定义 Android 视图实现提取文本
How to implement Extracted Text for a custom Android View
背景
Android 中的自定义编辑器视图能够通过 InputConnection
从系统键盘接收文本。我已经能够成功地做出这样的观点。但是,当设备处于横向模式时,系统有时会选择显示提取的文本视图。当用户在此模式下键入时,提取的文本视图应使用自定义视图中的相同文本进行更新。
我无法实现提取的文本视图功能。 ()
我也找不到任何清晰的文档或完整的示例来说明如何操作。 (以下是我读过的一些更好的东西:one, two, three, four)。
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);
}
}
activity_main.xml
<?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>
总结
我正在寻找一个规范的答案,它描述并举例说明了如何为自定义编辑器视图实现提取的文本更新。
如果我自己弄明白了,我会添加自己的答案。在那之前,我能做到的最好的只是 disable extracted text altogether。这并不理想。
您可以只删除提取的视图。我试过了,你的自定义视图在使用键盘时是可见的。
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
//remove extract view
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI;
return new MyInputConnection(this, true);
}
您可以使用 inputMethodManager.updateExtractedText(view, token, extractedText)
。
这个方法的第一个参数很简单。您可以在那里传递 CustomView 的实例。最后一个也。只需创建 ExtractedText 并像这样设置它的字段。
ExtractedText extractedText = new ExtractedText();
extractedText.text = "sample text";
更难的是传递正确的token。要了解此参数的正确值,您可以重写方法getExtractedText(ExtractedTextRequest request, int flags)
在您的 MyInputConnection class 中(令牌存储在请求对象中)。
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
currentToken = request.token;
return new ExtractedText();
}
I return empty ExtractedText object 来自此方法以使视图处于活动状态(默认情况下文本看起来像提示)。
你可以在这里找到我的解决方案https://github.com/ljarka/ExtractedText
背景
Android 中的自定义编辑器视图能够通过 InputConnection
从系统键盘接收文本。我已经能够成功地做出这样的观点。但是,当设备处于横向模式时,系统有时会选择显示提取的文本视图。当用户在此模式下键入时,提取的文本视图应使用自定义视图中的相同文本进行更新。
我无法实现提取的文本视图功能。 (
我也找不到任何清晰的文档或完整的示例来说明如何操作。 (以下是我读过的一些更好的东西:one, two, three, four)。
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);
}
}
activity_main.xml
<?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>
总结
我正在寻找一个规范的答案,它描述并举例说明了如何为自定义编辑器视图实现提取的文本更新。
如果我自己弄明白了,我会添加自己的答案。在那之前,我能做到的最好的只是 disable extracted text altogether。这并不理想。
您可以只删除提取的视图。我试过了,你的自定义视图在使用键盘时是可见的。
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
//remove extract view
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI;
return new MyInputConnection(this, true);
}
您可以使用 inputMethodManager.updateExtractedText(view, token, extractedText)
。
这个方法的第一个参数很简单。您可以在那里传递 CustomView 的实例。最后一个也。只需创建 ExtractedText 并像这样设置它的字段。
ExtractedText extractedText = new ExtractedText();
extractedText.text = "sample text";
更难的是传递正确的token。要了解此参数的正确值,您可以重写方法getExtractedText(ExtractedTextRequest request, int flags)
在您的 MyInputConnection class 中(令牌存储在请求对象中)。
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
currentToken = request.token;
return new ExtractedText();
}
I return empty ExtractedText object 来自此方法以使视图处于活动状态(默认情况下文本看起来像提示)。
你可以在这里找到我的解决方案https://github.com/ljarka/ExtractedText