“requestLayout() improperly called by…” error on Android 4.3

前端 未结 5 2199
一个人的身影
一个人的身影 2020-12-30 21:57

I have a simple Custom TextView that sets custom font in its constructor like the code below

public class MyTextView extends TextView {

    @Inject CustomTy         


        
相关标签:
5条回答
  • 2020-12-30 22:23

    I found where this bug occurs in my app. Although occurrence of this is not found in the code you provided (it may help if you have done this elsewhere in your code), it will hopefully help others fix this impossible-to-trace problem.

    I had a line (not added by me, of course):

    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.
        }
    });
    

    In my app, I did not need any listener, so removing this entire block fixed this problem. For those that need something like this, remember to remove the listener after the layout has changed (inside of this callback).

    0 讨论(0)
  • 2020-12-30 22:23

    Please check weather the Id of any view is repeating inside the same activity context. I was also getting the same warning, I was using a TextView repeatedly a loop with same id. I resolved the problem by using different ids each time.

    0 讨论(0)
  • 2020-12-30 22:33

    I fixed these warnings in my custom ListView item (LinearLayout subclass). This class implements Checkable, and has a setChecked(boolean checked) method that is called to indicate whether the item is 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"));
        }
    }
    

    I visually indicate the checked state by calling setTypeFace() on a textView in my view, toggling between regular and bold typefaces. These setTypeFace() calls were causing the warnings.

    To fix the problem, I created instance variables for the Typefaces in the class constructor and used them later, when changing the typeface, rather than calling Typeface.createFromAsset(...) every time:

    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);
        }
    }
    

    This is a pretty specific scenario, but I was pleasantly surprised to find a fix and maybe someone else is in the same situation.

    0 讨论(0)
  • 2020-12-30 22:34

    Looking into the Android source, this problem is described in a little more detail:

    requestLayout() was called during layout. If no layout-request flags are set on the requesting views, there is no problem. If some requests are still pending, then we need to clear those flags and do a full request/measure/layout pass to handle this situation.

    It appears that the problem may be related to Roboguice; see issue #88. The suggested solution there is to use @InjectView:

    You can now use @InjectView from inside a view class. Just call Injector.injectMembers() after you've populated your view, 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);
        }
    }
    

    Perhaps you should consider migrating RoboGuice.injectMembers(context, this) to the declaration of your View object using the @InjectView annotation.

    0 讨论(0)
  • 2020-12-30 22:34

    I met the same problem. That's because I was trying to set a view's position in the iOS way. You know in iOS set a view's position by set the view's left top value and width, height. But in Android, it should be (left, top, right, bottom). I did pay much attention on this. When I jump into the layout() definition, I read the method's comment, then I find out why the warning happened.

    0 讨论(0)
提交回复
热议问题