I'm trying to add a subclass of View to my activity_main.xml like this.
However, the device and emulator drop out of the app straight away. The error appears to be Error inflating class com.example.androidtest.PuzzleView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.androidtestapp.PuzzleView
android:id="#+id/puzzleView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="60"/>
<include
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="40"
layout="#layout/activity_input"/>
</LinearLayout>
and
package com.example.androidtestapp;
public class PuzzleView extends View {
public PuzzleView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
}
}
I think the problem is you need to have a constructor with AttributeSet attrs as a parameter
public PuzzleView(Context context, AttributeSet attrs) {
super(context, attrs);
//code
}
Related
I am trying to create a custom view, and I extends from LinearLayout:
public class CustomView extends LinearLayout {
private ImageView mPrevImgView;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
View root = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.custom, null);
this.addView(root);
mPrevImgView = root.findViewById(R.id.xx);
....
}
}
And the layout/custom.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/xx"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
.......
</LinearLayout>
Then I try to use it this way:
<CustomView android:layout_width.....>
...
</CustomView>
This works as expected.
However it seems that the CustomView itself is a LinearLayout, and it then add another LinearLayout in the constructor, this cause two LinearLayout nested which is unnecessary. I wonder if it is possible to avoid this?
// try this way
**custom.xml**
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/xx"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"/>
I'm having some trouble when I extend a LinearLayout.
The onClick event is never fired.
My code:
public class Tab extends LinearLayout {
public Tab(Context context) {
super(context);
init(context);
}
public Tab(Context context, AttributeSet attrs) {
super(context, attrs);
// ... get attrs ...
init(context);
}
public Tab(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
inflate(context, R.layout.tab, this);
// ... some layout tasks ...
iconView.requestLayout();
}
}
Layout tab.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal|center_vertical"
android:background="#drawable/bg_tab"
android:clickable="true"
android:duplicateParentState="true">
<ImageView
android:id="#+id/icon"
android:layout_width="0dp"
android:layout_height="0dp"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:layout_gravity="center_horizontal|center_vertical"
android:clickable="false"
android:duplicateParentState="true"/>
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:gravity="center_horizontal"
android:layout_gravity="center_horizontal|center_vertical"
android:textAllCaps="true"
android:textColor="#drawable/tab_text_color"
android:textSize="11sp"
android:duplicateParentState="true"/>
</LinearLayout>
If I put a eventListener on a Tab's child view, it works, but when attached to the Tab itself is doesn't.
Can someone see where my mistake is?
I just set android:clickable to false on rootView and works! =)
I'm getting a null pointer exception in my custom view (which is derived from a LinearLayout) because it can't find its child views. Here is the code:
public class MyView extends LinearLayout
{
public MyView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
private TextView mText;
#Override
protected void onFinishInflate()
{
super.onFinishInflate();
mText = (TextView) findViewById(R.id.text);
if (isInEditMode())
{
mText.setText("Some example text.");
}
}
}
Here is the layout (my_view.xml):
<?xml version="1.0" encoding="utf-8"?>
<com.example.views.MyView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:ellipsize="end"
android:maxLines="4"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Some text" />
</com.example.views.MyView>
And here is how I put it in the XML file:
<com.example.views.MyView
android:id="#+id/my_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
But when I try to preview it in the layout editor I get an NPE on mText.setText(...) because getViewById() returns null.
What's going on?
Clarification
The reason I expect this to work, is if I do
MyView v = (MyView)inflater.inflate(R.layout.my_view);
((TextView)v.findViewById(R.id.text)).setText("Foo");
everything works fine. Is that not what the layout inflater does when it goes through a layout file? In any case, how can I handle both situations correctly (without getting pointless nested views)?
In you XML file you are trying to use a custom view class (com.example.views.MyView) and in the same time trying to add a TextView inside. It's not possible.
Here is what you need to change:
You must inflate XML file in the code:
public MyView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
LayoutInflater.from(context).inflate(R.layout.<your_layout>.xml, this);
}
And modify the XML layout file like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:ellipsize="end"
android:maxLines="4"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:text="Some text" />
</LinearLayout>
Is there any way to adjust height and width of a custom component using XML attributes?
For example, I created a component and its layout.
Here is XML layout of the component:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="TextView" />
<TextView
android:id="#+id/textView2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="TextView" />
<TextView
android:id="#+id/textView3"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="TextView" />
</LinearLayout>
And here is a simple class that inflates this layout:
public class CustomComponent extends LinearLayout
{
public CustomComponent(Context context, AttributeSet attrs)
{
super(context, attrs);
LayoutInflater inflater = (LayoutInflater)context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup view = (ViewGroup)inflater.inflate(
R.layout.custom_component, null);
addView(view);
}
}
The custom component is used in layout of some activity that looks something like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<view
class = "com.tests.CustomComponent"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
The component is meant to be stretched to full size of a screen (that's why its layout parameters set to "fill_parent") but that is never happen.
Can anyone help me with this?
Seeing as your CustomComponent extends LinearLayout, you just need to inflate the layout directly into it (parsing this as the ViewGroup, as your CustomComponent will be the holding view):
public class CustomComponent extends LinearLayout
{
public CustomComponent(Context context, AttributeSet attrs)
{
super(context, attrs);
inflate( context, R.layout.custom_component, this );
}
}
If that doens't work, try supplying only the constructor that takes a context:
public class CustomComponent extends LinearLayout
{
public CustomComponent(Context context)
{
super(context);
inflate( context, R.layout.custom_component, this );
}
}
i have customview, i want to add that in the xml file i tried like this but i am getting this error
Custom view TouchImageView is not using the 2- or 3-argument View constructors;
XML attributes will not work
this is the xml i am using..
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<view
class="com.zoom.TouchImageView"
android:id="#+id/webView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
Add the constructor:
public TouchImageView(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
//TODO:
}
to your custom View class.