n4zg n4zg - 4 months ago 9
Android Question

Custom Linear Component Constructor not inflating XML

I have made a custom Number Picker extending a Linear Layout, i have issue with the constructors, for some reason the activity is not inflating the XML when i pass an enum to the constructor. Here is the code.

private TumblerSettings.TumblerTypes tumblerTypes;

public Tumbler(Context context, TumblerListener tumblerCallBack, TumblerSettings.TumblerTypes
tumblerTypes)
{
super(context);
this.mTumblerCallBack = tumblerCallBack;
this.tumblerTypes = tumblerTypes;
Log.i("sss", "Tumbler1: " + String.valueOf(tumblerTypes));
updateValue();
initControl(context);
//setCustomObjectListener(mTumblerCallBack);
}

public Tumbler(Context context, AttributeSet attrs, TumblerSettings.TumblerTypes
tumblerTypes)
{
super(context, attrs);
this.tumblerTypes = tumblerTypes;
Log.i("sss", "Tumbler2: " + String.valueOf(tumblerTypes));
updateValue();
initControl(context);
}

public Tumbler(Context context, AttributeSet attrs, int defStyle, TumblerSettings.TumblerTypes
tumblerTypes)
{
super(context, attrs, defStyle);
this.tumblerTypes = tumblerTypes;
Log.i("sss", "Tumbler3: " + String.valueOf(tumblerTypes));
updateValue();
initControl(context);

}


And im calling it with this code

mTumbler = new Tumbler(MainActivity.this, new Tumbler.TumblerListener()
{
@Override
public void tumblerValue(final String value)
{
valueTextView.setText("value :" + value);
}
}, TumblerSettings.TumblerTypes.BRIGHTNESS);


The error im getting is


E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.wheelsample/com.example.wheelsample.MainActivity}: android.view.InflateException: Binary XML file line #26: Error inflating class com.example.wheelsample.tumblers.Tumbler
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)


Any suggestions would be gratefully appreciated. Thank you

XML Code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context="com.example.wheelsample.DualNumberPicker">

<LinearLayout
android:layout_width="75dp"
android:layout_height="120dp"
android:background="@drawable/assets_tmb_wide"
android:orientation="horizontal">

<com.example.wheelsample.TumblerNumberPicker
android:id="@+id/bpp"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"/>

</LinearLayout>



Answer

It seems that there is some confusion in the way you are trying to create your view. You have two options for creating a view.

XML inflation:

You declare your view in your XML file and, after calling setContentView from your Activity, you can use findViewById() to get an instance to it.

Example

Let's say your custom view is called Tumbler and your package name is com.example and you have it declared like this in your XML file:

<com.example.Tumbler
  android:id="@+id/my_tumbler"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />

Then you'll be able to get an instance to it by calling:

Tumbler tumbler = (Tumbler) findViewById(R.id.my_tumbler);

Programmatic instantiation

If you opt for not using XML at all, you can create your own view instance:

Tumbler tumbler = new Tumbler(this);

Then you'll have to add it to a parent view in your view hierarchy by calling addView(). But this is not really what you want, so I suggest you take the first approach.

This code:

mTumbler = new Tumbler(MainActivity.this, new Tumbler.TumblerListener()
    {
        @Override
        public void tumblerValue(final String value)
        {
            valueTextView.setText("value :" + value);
        }
    }, TumblerSettings.TumblerTypes.BRIGHTNESS);

Can be replaced by:

mTumbler = (Tumbler) findViewById(R.id.your_tumbler_id_just_like_in_xml_file);

And then you call a setter method to set your enum value:

mTumbler.setTumblerType(TumblerSettings.TumblerTypes.BRIGHTNESS)

The whole thing is that the system calls View(Context context, AttributeSet attrs) constructor when it inflates an XML file. You can't just add custom arguments to your constructors, unless if you are going to create your instances dynamically in Java. Use a setter method instead.

For a nice explanation on how view constructors work, check this page:

http://blog.danlew.net/2016/07/19/a-deep-dive-into-android-view-constructors/