28

我有一个简单的自定义 TextView,它在其构造函数中设置自定义字体,如下面的代码

public class MyTextView extends TextView {

    @Inject CustomTypeface customTypeface;

    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        RoboGuice.injectMembers(context, this);
        setTypeface(customTypeface.getTypeface(context, attrs));
        setPaintFlags(getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }
}

从 Gingerbread 到 JB 4.2 都可以正常工作。但是,当我在 Android 4.3 手机上显示我的自定义文本视图时,adb logcat 中充斥着以下消息。

10-05 16:09:15.225: WARN/View(9864): requestLayout() improperly called by com.cmp.views.MyTextView{42441b00 V.ED.... ......ID 18,218-456,270 #7f060085 app:id/summary} during layout: running second layout pass
10-05 16:09:15.225: WARN/View(9864): requestLayout() improperly called by com.cmp.views.MyTextView{423753d0 V.ED.... ......ID 26,176-742,278 #7f060085 app:id/summary} during layout: running second layout pass

我注意到,它确实会减慢 UI 的速度。有什么想法为什么会在 4.3 上发生?

感谢你的帮助。

4

5 回答 5

6

我在我的应用程序中发现了这个错误发生的位置。尽管在您提供的代码中没有发现这种情况(如果您在代码的其他地方这样做可能会有所帮助),但它有望帮助其他人解决这个无法追踪的问题。

我有一行(当然不是我添加的):

myView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        //this would then make a call to update another view's layout.
    }
});

在我的应用程序中,我不需要任何侦听器,因此删除整个块解决了这个问题。对于那些需要这样的人,请记住在布局更改后(在此回调内部)删除侦听器。

于 2014-03-28T17:34:22.383 回答
2

查看 Android 源代码,更详细地描述了这个问题:

requestLayout()在布局期间被调用。如果没有在请求视图上设置布局请求标志,则没有问题。如果某些请求仍处于待处理状态,那么我们需要清除这些标志并执行完整的请求/测量/布局传递以处理这种情况。

看来问题可能与 Roboguice 有关;见问题#88。建议的解决方案是使用@InjectView:

您现在可以在视图类中使用 @InjectView。填充视图后只需调用 Injector.injectMembers() ,ala:

public class InjectedView extends FrameLayout {

    @InjectView(R.id.view1) View v;

    public InjectedView(Context context) {
        super(context);
        final View child = new View(context);
        child.setId(R.id.view1);
        addView(child);

        RoboGuice.getInjector(context).injectMembers(this);
    }
}

也许您应该考虑RoboGuice.injectMembers(context, this)使用 @InjectView 注释迁移到 View 对象的声明。

于 2014-02-02T17:56:35.830 回答
1

我在我的自定义ListView项目(LinearLayout子类)中修复了这些警告。这个类实现Checkable了 ,并且有一个setChecked(boolean checked)方法被调用来指示该项目是否被检查:

@Override
public void setChecked(boolean checked) {
    mChecked = checked;
    TextView textView = (TextView)this.findViewById(R.id.drawer_list_item_title_text_view);
    if(mChecked) {
        textView.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/Andada-Bold.ttf"));
    }
    else {
        textView.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/Andada-Regular.ttf"));
    }
}

setTypeFace()我通过在视图中调用 textView 来直观地指示选中状态,在常规字体和粗体字体之间切换。这些setTypeFace()电话引起了警告。

为了解决这个问题,我在类构造函数中为 s 创建了实例变量,Typeface然后在更改字体时使用它们,而不是Typeface.createFromAsset(...)每次都调用:

private Typeface mBoldTypeface;
private Typeface mRegularTypeface;

public DrawerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initTypefaces();
}

private void initTypefaces() {
        this.mBoldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Andada-Bold.ttf");
        this.mRegularTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Andada-Regular.ttf");
}

@Override
public void setChecked(boolean checked) {
    mChecked = checked;
    TextView textView = (TextView)this.findViewById(R.id.drawer_list_item_title_text_view);
    if(mChecked) {
        textView.setTypeface(mBoldTypeface);
    }
    else {
        textView.setTypeface(mRegularTypeface);
    }
}

这是一个非常具体的场景,但我很惊喜地找到了解决方法,也许其他人也处于同样的情况。

于 2015-01-02T19:20:35.757 回答
0

请检查天气,任何视图的 ID 在同一活动上下文中重复。我也得到了同样的警告,我反复使用 TextView 一个具有相同 ID 的循环。我通过每次使用不同的 id 解决了这个问题。

于 2014-09-04T15:50:00.467 回答
0

我遇到了同样的问题。那是因为我试图以 iOS 方式设置视图的位置。你知道在 iOS 中通过设置视图的左上角值和宽度、高度来设置视图的位置。但在 Android 中,应该是(左、上、右、下)。我确实非常关注这一点。当我跳入layout()定义时,我阅读了方法的注释,然后我找出了警告发生的原因。

于 2016-04-27T01:02:42.670 回答