3

Say I have this class MyView:

public class MyView extends GLSurfaceView {
    private MyRenderer mRenderer;

    public MyView(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);
        init(ctx);
    }

    private void init(Context ctx) {
        mRenderer = new MyRenderer(ctx);
        setRenderer(mRenderer);
    }

    @Override
    public void setBackground(Drawable background) {
        mRenderer.setBackground(background);
    }
}

That is inflated by MyActivity like this:

public class MyActivity extends Activity {
    private MyView mView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
    }

    protected void init() {
        setContentView(R.layout.my_layout);
        mView = (MyView) findViewById(R.id.my_view);
    }
}

To my knowledge setBackground is called by the inflater in setContentView, before init is called in MyView, so mRenderer has not been initialized yet.

It seems like a catch 22, because the view's attributes can't be set without the view's initialization, which happens after the attributes are set.

This is the layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/my_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/background" >

    <com.developer.app.MyView
        android:id="@+id/my_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/background"
        />

    <TextView
        android:id="@+id/left_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:background="@drawable/left_arrow"
        />

    <TextView
        android:id="@+id/right_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:background="@drawable/right_arrow"
        />

    <TextView
        android:id="@+id/home_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/home"
        />
</RelativeLayout>
rraallvv
  • 2,875
  • 6
  • 30
  • 67
  • Did you actually run this code ? I am assuming the view `MyView` is part of the layout XML `R.layout.my_layout`. In which case, `setContentView` would have cause the constructor on `MyView` to be called. Anyways in all goodness, the `setBackground` is an instance method and there is no way it can be invoked in your code flow before the renderer being initialized (you are initializing the renderer in the constructor) – Dibzmania Jan 16 '17 at 12:29
  • @Dibzmania I have this code working commenting out `setBackground` in `MyView`, or calling the super class's `setBackground` method. With the former the view would have a black background. With the later only the background is rendered by the super class (I guess) but not my geometry even when all the draw calls are there in the renderer's `onDrawFrame` method. – rraallvv Jan 16 '17 at 12:46
  • try calling `setZOrderOnTop(true)` in your constructor or init method. And then uncomment your `setBackground` method and see if it works – Dibzmania Jan 16 '17 at 12:53
  • @Dibzmania `setZOrderOnTop` would hide the UI interface, which are some drawables on top of `MyView` in a `RelativeLayout`. Everything was working fine until I tried to set the background image from the XML layout instead of the activity’s `init` method after the `my_view` is inflated. – rraallvv Jan 16 '17 at 13:19
  • Can you post your layout file ? – Dibzmania Jan 16 '17 at 13:26
  • Just few pointers - First thing is SurfaceView has two parts.The surface and the view. The Surface is a separate layer that is composited behind the layer with all the Views, so normally the SurfaceView's View is just a transparent window which tells the Android view system where the surface might peek though. Second thing is you cannot set a background drawable on a surfaceview (which you might be trying by putting in the XML), but you have to manually draw it on the surface (which you might have been doing by calling the renderer to set the background). Just pointers !!! – Dibzmania Jan 16 '17 at 13:46
  • @Dibzmania, I updated the question with the layout, what I wanted is the view to have a drawable background set from the xml file, in order to avoid some black flickering while the textures are loaded by the renderer, then when all the textures have been loaded, I just call `setBackground(null)` and the view’s geometry kicks in, including a quad with the same image as the background, so the transition is smooth. – rraallvv Jan 16 '17 at 16:13

3 Answers3

1

What i understood from your question. You need attributes of views in oncreate(). But unable to do so. the reason is at that point UI is not initialized yet. there is work around. this link might help.

getWidth() and getHeight() of View returns 0

Community
  • 1
  • 1
Abdullah Raza
  • 600
  • 3
  • 9
1

You are right. setBackground() is called from View's constructor if android:background attribute was parsed. In your case it called here:

super(ctx, attrs);

If you want to set background to mRenderer, you can do it in init:

private void init(Context ctx) {
    mRenderer = new MyRenderer(ctx);
    setRenderer(mRenderer);
    final Drawable background = getBackground();
    if (background != null) {
        mRenderer.setBackground(background);
    }
}

and add a null-check in setBackground, because this method can be called from superclass' constructor before you set some value to mRenderer

@Override
public void setBackground(Drawable background) {
    if (mRenderer != null) {
        mRenderer.setBackground(background);
    }
}
Kirill
  • 7,580
  • 6
  • 44
  • 95
0

You have initialize its three functions for example and xml and java is as you are doing it.

public class MyEditText extends EditText {
    public MyEditText(Context context) {
        super(context);
        this.setTextColor(Color.parseColor("#4789da"));
        this.setBackgroundResource(R.drawable.edittext_back);
        this.setTextSize(18);
        this.setPadding(5,5,5,5);
    }

    public MyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setTextColor(Color.parseColor("#4789da"));
        this.setBackgroundResource(R.drawable.edittext_back);
        this.setTextSize(18);
        this.setPadding(5,5,5,5);
    }

    public MyEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.setTextColor(Color.parseColor("#4789da"));
        this.setBackgroundResource(R.drawable.edittext_back);
        this.setTextSize(18);
        this.setPadding(5,5,5,5);
    }
}
Harmantj
  • 182
  • 2
  • 11