【问题标题】:EditText scale with selection带选择的 EditText 缩放
【发布时间】:2014-04-07 17:19:56
【问题描述】:

我有一个EditText,我想放大它,并使用setScaleX/setScaleY 滚动,它工作正常——文本正在正确的位置进行编辑。

但是当我尝试选择文本时 - 它会将选择句柄绘制到位置,例如文本未缩放时。已知bug。

这是预期的结果,因为手柄是在与视图大小相关的弹出窗口上绘制的。

android.widget.Editor 上的所有操作都针对其字段 private TextView mTextView;。如果我们通过反射设置自己的编辑器,我不知道如何处理私有方法,这是不可覆盖的。

选择句柄也绘制在弹出窗口android.widget.Editor.HandleView#HandleView在布局中计算的坐标上,我只需要DynamicLayout,但它对我们的目的没有区别。

方法android.text.Layout#getPrimaryHorizontal(int, boolean) 是公共的,它的值可以成倍增加,但是为此我们需要扩展和覆盖私有方法android.widget.TextView#makeSingleLayout,但这是一个问题。

我们也可以使用所有必需的覆盖方法实现自己的布局,但是我们可以覆盖的所有方法都标有@hide 注释,并且没有可以通过反射访问的字段。

下一个屏幕截图显示为 2x 缩放

PS:任务的上下文是一个带有捏拉缩放编辑文本的编辑器。计算大小的文本重新布局不是解决方案。因为我需要每个屏幕尺寸的便携式文档。

【问题讨论】:

  • 请考虑格式化那堵文字墙。读起来不太容易。
  • 对不起,@Avanz。现在我不能接受你的解决方案,因为不能批准未检查的解决方案。至于我,很多跨度都有公制的影响。我也有很多自定义跨度,所以在这个解决方案中我应该覆盖每个跨度以返回缩放大小。我有 22 个自定义跨度、字符和段落。首先,我会尝试您的解决方案,然后解决方案将被接受。
  • 好的。有你的时间,试一试。有任何事情请告诉我。
  • 此功能移至第二版。实际日期是八月。

标签: java android editor pinchzoom spanned


【解决方案1】:

您可以使用MetricAffectingSpan 做到这一点。这是一个例子:

package android.text.style;

import android.os.Parcel;
import android.text.ParcelableSpan;
import android.text.TextPaint;
import android.text.TextUtils;

public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan {

    private final int mSize;
    private boolean mDip;

    /**
     * Set the text size to <code>size physical pixels.
     */
    public AbsoluteSizeSpan(int size) {
        mSize = size;
    }

    /**
     * Set the text size to <code>size physical pixels,
     * or to <code>size device-independent pixels if
     * <code>dip is true.
     */
    public AbsoluteSizeSpan(int size, boolean dip) {
        mSize = size;
        mDip = dip;
    }

    public AbsoluteSizeSpan(Parcel src) {
        mSize = src.readInt();
        mDip = src.readInt() != 0;
    }

    public int getSpanTypeId() {
        return TextUtils.ABSOLUTE_SIZE_SPAN;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mSize);
        dest.writeInt(mDip ? 1 : 0);
    }

    public int getSize() {
        return mSize;
    }

    public boolean getDip() {
        return mDip;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        if (mDip) {
            ds.setTextSize(mSize * ds.density);
        } else {
            ds.setTextSize(mSize);
        }
    }

    @Override
    public void updateMeasureState(TextPaint ds) {
        if (mDip) {
            ds.setTextSize(mSize * ds.density);
        } else {
            ds.setTextSize(mSize);
        }
    }
}

参考:Java Source Code Warehouse project

您需要使用 MetricAffectingSpan 和 wrap(CharacterStyle cs) - 这允许将 CharacterStyle 应用于给定 Spanned 的单个区域。

在您的子类中,覆盖 onTouch 并将其值传递给 ScaleGestureDetector。将检测到的比例存储为成员变量。

覆盖 onDraw,并在调用 super.onDraw 之前使用您的比例值调用 canvas.scale()。正如您在 AbsoluteSizeSpan 中看到的那样,使用 AbsoluteSizeSpan(Parcel src) 将获得您希望调整大小的文本,然后您应用 updateDrawState。

【讨论】:

  • 您能否详细解释一下这如何解决手柄无法以正确大小呈现的问题?
  • 我真的没有时间尝试解决方案。但我很快就会回到它。有谁查过,欢迎评论。 Avanz,感谢您提供最完整的回答。
  • /** @hide */ public static final int ABSOLUTE_SIZE_SPAN = 16;
【解决方案2】:

您是否尝试对这些元素应用不同的样式?我认为它应该在一些条件下起作用。

<item name="android:textSelectHandle">@drawable/text_select_handle_middle</item>
<item name="android:textSelectHandleLeft">@drawable/text_select_handle_left</item>
<item name="android:textSelectHandleRight">@drawable/text_select_handle_right</item>

【讨论】:

  • 您能解释一下您认为这将如何解决不正确的重新调整问题吗?
  • 问题是您正在处理的错误无法通过我所知道的任何标准方法“解决”。您可能已经尝试过一些非标准方法。我要建议的是设置选择的样式并动态更改可绘制对象,在此过程中缩放(编辑:和定位)它们。请注意,我没有尝试过,也许明天我会摆弄它,因为 GMT 正在杀死我。
  • 啊,所以你认为如果在调整大小后改变样式,手柄可能会适当调整大小?
  • 这只是一个想法,我想值得一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-02
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
  • 2020-08-16
  • 2015-12-21
相关资源
最近更新 更多