Don't understand why my compound view doesn't want to work.
Caused by: android.view.InflateException: Binary XML file line #186: Error inflating class com.igor.customviews.CompoundEditText
There are constructors. As you see I didn't miss super and pass init() to all of them.
public class CompoundEditText extends RelativeLayout {
private String editTextHint;
private int resDrawableLeft, resDrawableRight, inputType;
private EditTextRegular editText;
private ImageView customDrawableLeft, customDrawableRight;
public CompoundEditText(Context context) {
super(context);
init();
}
public CompoundEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.CompoundEditText,
0, 0);
try {
editTextHint = a.getString(R.styleable.CompoundEditText_hint);
resDrawableLeft = a.getResourceId(R.styleable.CompoundEditText_left_drawable_src, 0);
resDrawableRight = a.getResourceId(R.styleable.CompoundEditText_right_drawable_src, 0);
editText.setHint(editTextHint);
customDrawableLeft.setImageResource(resDrawableLeft);
customDrawableRight.setImageResource(resDrawableRight);
} finally {
a.recycle();
}
}
public CompoundEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
inflate(getContext(), R.layout.compound_edit_text, this);
editText = (EditTextRegular) findViewById(R.id.edit_text);
customDrawableLeft = (ImageView) findViewById(R.id.drawable_left);
customDrawableRight = (ImageView) findViewById(R.id.drawable_right);
}
}
Error is mainly Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown> as far, as I understand and it refers to this line: inflate(getContext(), R.layout.compound_edit_text, this);
I can't figure out why it doesn't help, because the same way I made another compound view and it works fine.
Hope your fresh look on the code will help to solve the problem. Thank you.
EDIT
Just try to add it to layout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/main_bg_color"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
...
<com.igor.customviews.CompoundEditText
android:id="#+id/test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
Related
I have a hierarchy of custom views that looks like this:
Activity(RelativeLayout) -> ParentLayout(FrameLayout) -> ChildLayout(LinearLayout)
The activity and parent layout are added and displayed just fine, but the child is not. I have looked at the hierarchy viewer in the device monitor to confirm it is not being added to the view hierarchy.
Really all I'm trying to do here is create a view hierarchy so I can play around with handling touch events at various places in the view.
Here is everything:
main_activity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<net.openeye.touchevents.ParentLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#558833" />
</RelativeLayout>
parent_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<net.openeye.touchevents.ParentLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<net.openeye.touchevents.ChildLayout
android:id="#+id/child_view"
android:layout_width="300dp"
android:layout_height="300dp" />
</net.openeye.touchevents.ParentLayout>
ParentLayout.java:
public class ParentLayout extends FrameLayout implements View.OnTouchListener {
public ParentLayout(Context context) {
super(context);
}
public ParentLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ParentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
child_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<net.openeye.touchevents.ChildLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#0066dd"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hi"/>
</net.openeye.touchevents.ChildLayout>
ChildLayout.java:
public class ChildLayout extends LinearLayout {
public ChildLayout(Context context) {
super(context);
}
public ChildLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ChildLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
What am I missing? I have another project that is basically set up the same way, except the child views are dynamically inflated and added, instead of being directly added in the xml layout files. This seems like it should work and I don't understand why it doesn't.
So it looks like when you have a custom view class, you don't want to have the view of the layout file be the same type as the custom class. i.e., if I have ParentLayout.java, I don't want parent_layout.xml's root to be <net.openeye.TouchEvents.ParentLayout>. It seems that when you want both a custom layout file and custom view class, you need to have the view class inflate the layout. If the layout has an element (the root, on this case) that is the same as the class, it will cause infinite recursion as the view inflates the layout, which instantiates the class, which inflates the layout... and so on.
I got this to work finally by making the following changes:
parent_layout.xml:
Change the root element from net.openeye.TouchEvents.ParentLayout to the class it extends, FrameLayout. It now looks like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- ... -->
</FrameLayout>
child_layout.xml:
Change the root element from net.openeye.TouchEvents.ChildLayout to the class it extends, LinearLayout. It now looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="300dp"
android:orientation="vertical">
<!-- ... -->
</LinearLayout>
ParentLayout.java: Inflate it's layout during instantiation. It now looks like this:
public ParentLayout(Context context) {
super(context);
init(context);
}
public ParentLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ParentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
inflate(context, R.layout.parent_layout, this);
}
ChildLayout.java: Same thing as ParentLayout.java, but inflate child_layout.
After getting this working and thinking about why this is happening, it makes sense that this is how it works.
I'm trying to write some tests for a custom view, but I am having trouble inflating the custom view in my test case. The error I get is
android.view.InflateException: <merge /> can be used only with a valid ViewGroup root and attachToRoot=true
at android.view.LayoutInflater.inflate(LayoutInflater.java:458)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
at com.androidas.models.ui.order.MyLocationViewTest.setUp(MyLocationViewTest.java:45)
I even tried making a dummy activity (TestActivity) with a tag in it to try to inflate it
public class MyLocationView extends RelativeLayout {
private TextView mTextEta;
private TextView mTextOnTime;
private Date mMeetTime;
private CalendarManager mCalendarManager;
public MyLocationView(Context context) {
this(context, null);
}
public MyLocationView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLocationView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LayoutInflater.from(context)
.inflate(R.layout.v_mylocation, this, true);
mTextEta = (TextView) findViewById(R.id.order_statusTracking_txt_myEta);
mTextOnTime = (TextView) findViewById(R.id.order_statusTracking_txt_myDelay);
}
}
layout
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
>
<ImageView
android:id="#+id/order_statusTracking_img_walking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_walk"
/>
<TextView
android:id="#+id/order_statusTracking_txt_myEta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/spacing_small"
android:layout_toRightOf="#+id/order_statusTracking_img_walking"
android:layout_toEndOf="#+id/order_statusTracking_img_walking"
android:gravity="center_vertical"
tools:text="Arrive in 7min"
style="#style/HeaderText"
/>
<TextView
android:id="#+id/order_statusTracking_txt_myDelay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/order_statusTracking_txt_myEta"
android:layout_below="#+id/order_statusTracking_txt_myEta"
android:layout_marginTop="#dimen/spacing_normal"
tools:text="On Time"
style="#style/InfoText.Black"
/>
</merge>
and Test case:
#RunWith(RobolectricTestRunner.class)
#Config(emulateSdk = 18)
public class MyLocationViewTest {
MyLocationView mLocation;
TextView mTextDelay;
Trip mTrip;
CalendarManager mCalendarManager;
Date meetupTime;
#Before
public void setUp() {
Activity activity = Robolectric.buildActivity(TestActivity.class).create().get();
mLocation = (MyLocationView) LayoutInflater.from(activity).inflate(R.layout.v_mylocation, null);
mTextDelay = (TextView) mLocation.findViewById(R.id.order_statusTracking_txt_myDelay);
}
OK, 1 year later but here is the weird thing that worked for me:
MyCustomView mView = (MyCustomView) LayoutInflater
.from(RuntimeEnvironment.application)
.inflate(R.layout.my_custom_view_layout,
new MyCustomView(RuntimeEnvironment.application),
true);
I am trying to extend a cardview to set the background image. I know that this can not be done with normal cardview. I have searched net and found plenty of solutions for setting a background color to the card view but none for image.
My code to do so:
public class CCView extends CardView {
public CCView (Context context) {
super(context);
init();
}
public CCView (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CCView (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setBackground(getResources().getDrawable(R.drawable.cc_background));
}
}
I get this exception when I populate the code from XML
android.graphics.drawable.BitmapDrawable cannot be cast to android.support.v7.widget.RoundRectDrawableWithShadow
Any solution?
As CardView extends FrameLayout you can layer layouts on top of it. To get around the problem you're having, I'd try adding a blank view "underneath" all the other elements in your view, and then set that view to inherit the state of its parent. Something like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent"
card_view:cardBackgroundColor="#DDFFFFFF"
card_view:cardElevation="#dimen/card_elevation">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true"
android:background="#drawable/card_background"/>
<LinearLayout
....
....
....
/LinearLayout>
</android.support.v7.widget.CardView>
I created a custom view for Android which renders two inner views to store a key and a value in two columns. The class looks like this:
public class KeyValueRow extends RelativeLayout {
protected TextView mLabelTextView;
protected TextView mValueTextView;
public KeyValueRow(final Context context) {
super(context);
init(context, null, 0);
}
public KeyValueRow(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public KeyValueRow(final Context context,
final AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
protected void init(final Context context,
final AttributeSet attrs, int defStyle) {
View layout = ((LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.key_value_row, this, true); // line 46
mLabelTextView = (TextView) layout.findViewById(
R.id.key_value_row_label);
mValueTextView = (TextView) layout.findViewById(
R.id.key_value_row_value);
}
public void setLabelText(final String text) {
mLabelTextView.setText(text);
}
public void setValueText(final String text) {
mValueTextView.setText(text);
}
}
The associated layout file layout/key_value_row.xml looks like this:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1.0">
<TextView
android:id="#+id/key_value_row_label"
style="#style/KeyValueLabel"
android:layout_weight=".55"
tools:text="Label"/>
<TextView
android:id="#+id/key_value_row_value"
style="#style/KeyValueValue"
android:layout_weight=".45"
tools:text="Value"/>
</LinearLayout>
This can be used as follows in a layout:
<com.example.myapp.customview.KeyValueRow
android:id="#+id/foobar"
style="#style/KeyValueRow" />
Until here everything works fine!
The challenge
Now, I want to allow custom settings for the layout_weight attributes of both inner TextViews. Therefore, I prepared the attributes in values/attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="KeyValueRow">
<attr name="label_layout_weight" format="float" />
<attr name="value_layout_weight" format="float" />
</declare-styleable>
</resources>
First question would be: is float the correct format for layout_weight?
Next, I would apply them in the layout file:
<?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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:weightSum="1.0">
<TextView
android:id="#+id/key_value_row_label"
style="#style/KeyValueLabel"
android:layout_weight="?label_layout_weight"
tools:text="Label"/>
<TextView
android:id="#+id/key_value_row_value"
style="#style/KeyValueValue"
android:layout_weight="?value_layout_weight"
tools:text="Value"/>
</LinearLayout>
Then they can be used in the example:
<com.example.myapp.customview.KeyValueRow
android:id="#+id/foobar"
style="#style/KeyValueRow"
custom:label_layout_weight=".25"
custom:value_layout_weight=".75" />
When I run this implementation the following exception is thrown:
Caused by: java.lang.NumberFormatException: Invalid float: "?2130772062"
at java.lang.StringToReal.invalidReal(StringToReal.java:63)
at java.lang.StringToReal.parseFloat(StringToReal.java:310)
at java.lang.Float.parseFloat(Float.java:300)
at android.content.res.TypedArray.getFloat(TypedArray.java:288)
at android.widget.LinearLayout$LayoutParams.<init>(LinearLayout.java:1835)
at android.widget.LinearLayout.generateLayoutParams(LinearLayout.java:1743)
at android.widget.LinearLayout.generateLayoutParams(LinearLayout.java:58)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:757)
at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
at com.example.myapp.customview.KeyValueRow.init(KeyValueRow.java:46)
at com.example.myapp.customview.KeyValueRow.<init>(KeyValueRow.java:28)
... 33 more
You can use
private void applyAttributes(Context context, AttributeSet attrs) {
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.KeyValueRow, 0, 0);
try {
labelWeight = a.getFloat(
R.styleable.KeyValueRow_label_layout_weight, 0.55f);
valueWeight = a.getFloat(
R.styleable.KeyValueRow_value_layout_weight, 0.45f);
} finally {
a.recycle();
}
}
and after this you can apply this via:
mLabelTextView = (TextView) layout.findViewById(R.id.key_value_row_label);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, labelWeight);
mLabelTextView.setLayoutParams(layoutParams);
To get it running replace android:layout_weight="?label_layout_weight" with some default value such as android:layout_weight="0.5" in layout/key_value_row.xml. It will be overwritten.
I have seen this error posted before but none of the answers seem to fix my problem so I am not really sure what is going on. It is failing when it tries to inflate my class in the xml.
XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#EEE"
>
<android.view.SurfaceView
android:id="#+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</android.view.SurfaceView>
<com.commonsware.android.picture.PictureDemo.DrawOnTop
android:id="#+id/grid"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
</com.commonsware.android.picture.PictureDemo.DrawOnTop>
</FrameLayout>
Class:
class DrawOnTop extends View
{
public DrawOnTop(Context context)
{
super(context);
}
public DrawOnTop(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public DrawOnTop(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas)
{
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawText("Test Text", 10, 10, paint);
canvas.drawBitmap(bitmap, 0, 0, null);
super.onDraw(canvas);
}
}
Error:
02-11 16:06:25.456: E/AndroidRuntime(11717): Caused by: android.view.InflateException: Binary XML file line #14: Error inflating class com.commonsware.android.picture.PictureDemo.DrawOnTop
I have all the constructors and dont see any other problem, what am I missing?
Try separating DrawOnTop to another file within the same package.