首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自定义TextView - setText()在构造函数之前调用

自定义TextView - setText()在构造函数之前调用
EN

Stack Overflow用户
提问于 2014-08-29 09:58:45
回答 4查看 6.2K关注 0票数 13

我的CustomTextView.有问题我正在尝试从我的layout-xml文件中获取一个自定义值,并在我的setText()方法中使用这个值。不幸的是,setText()方法在构造函数之前调用了,因此不能在该方法中使用自定义值。

下面是我的代码(细分为相关部分):

CustomTextView.class

代码语言:javascript
复制
public class CustomTextView extends TextView {

    private float mHeight;
    private final String TAG = "CustomTextView";
    private static final Spannable.Factory spannableFactory = Spannable.Factory.getInstance();

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.d(TAG, "in CustomTextView constructor");
        TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
        this.mHeight = values.getDimension(R.styleable.CustomTextView_cHeight, 20);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        Log.d(TAG, "in setText function");
        Spannable s = getCustomSpannableString(getContext(), text);
        super.setText(s, BufferType.SPANNABLE);
    }

    private static Spannable getCustomSpannableString(Context context, CharSequence text) {
        Spannable spannable = spannableFactory.newSpannable(text);
        doSomeFancyStuff(context, spannable);
        return spannable;
    }

    private static void doSomeFancyStuff(Context context, Spannable spannable) {
        /*Here I'm trying to access the mHeight attribute.
        Unfortunately it's 0 though I set it to 24 in my layout 
        and it's correctly set in the constructor*/
    }
}

styles.xml

代码语言:javascript
复制
<declare-styleable name="CustomTextView">
    <attr name="cHeight" format="dimension"/>
</declare-styleable>

layout.xml

代码语言:javascript
复制
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ctvi="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.mypackage.views.CustomTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/my_fancy_string"
        android:textSize="16sp"
        ctvi:cHeight="24dp" />

</LinearLayout>

作为一个证明-这是LogCat输出:

代码语言:javascript
复制
30912-30912/com.mypackage.views D/CustomTextView﹕ in setText function
30912-30912/com.mypackage.views D/CustomTextView﹕ in CustomTextView constructor

因此,如您所见,在构造函数之前调用setText()方法。这有点奇怪,为了在setText方法中使用我的自定义属性(cHeight),我不知道需要更改什么。

提前感谢您的帮助!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-08-29 10:03:56

它是TextView super()构造函数,它根据属性值调用setText()

如果在设置文本值时确实需要访问自定义属性,也可以为文本使用自定义属性。

票数 8
EN

Stack Overflow用户

发布于 2016-06-06 22:23:01

我不认为这些解决方案都是好的,IMHO。如果您只是使用一个自定义方法,比如setCustomText(),而不是覆盖自定义TextView.setText(),那该怎么办?我认为它在可伸缩性方面可能会更好,而黑客/重写TextView的实现可能会使您陷入未来的问题。

干杯!

票数 2
EN

Stack Overflow用户

发布于 2016-05-27 15:46:23

首先,记住在使用TypedArray之后始终回收它。

因此,TextView在其构造过程中调用#setText(CharSequence text, BufferType type)定义了对setText的延迟调用,如下所示:

代码语言:javascript
复制
private Runnable mDelayedSetter;
private boolean mConstructorCallDone;

public CustomTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    Log.d(TAG, "in CustomTextView constructor");
    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
    this.mHeight = values.getDimension(R.styleable.CustomTextView_cHeight, 20);
    mConstructorCallDone = true;
}

然后在您的setText-override中:

代码语言:javascript
复制
public void setText(final CharSequence text, final TextView.BufferType type) {
    if (!mConstructorCallDone) {
        // The original call needs to be made at this point otherwise an exception will be thrown in BoringLayout if text contains \n or some other characters.
        super.setText(text, type);
        // Postponing setting text via XML until the constructor has finished calling
        mDelayedSetter = new Runnable() {
            @Override
            public void run() {
                CustomTextView.this.setText(text, type);
            }
        };
        post(mDelayedSetter);
    } else {
        removeCallbacks(mDelayedSetter);
        Spannable s = getCustomSpannableString(getContext(), text);
        super.setText(s, BufferType.SPANNABLE);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25565939

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档