Android - Cannot get custom LinearLayout view to move with TranslateAnimation - android

I'm trying to do something simple - I have a custom LinearLayout view that I want to move across the screen using the TranslateAnimation. To test out the base case, I put the code in the constructor of my custom view to translate it as soon as it is created. But nothing happens, and the view stays put. Any idea why? I have pasted the relevant code below:
My custom LinearLayout View:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_view, this);
mText = (TextView) findViewById(R.id.my_text);
mImage = (ImageView) findViewById(R.id.my_picture);
//Test simple translate animation
TranslateAnimation translateMyView = new TranslateAnimation(10, 10, 5, 5);
translateMyView.setFillAfter(true);
translateMyView.setDuration(1000);
this.startAnimation(translateMyView);
}
The XML of this custom view:
<?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="match_parent"
android:orientation="vertical"
android:background="#drawable/border">
<TextView
android:id="#+id/my_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Example Text"/>
<ImageView
android:id="#+id/my_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
And the way I have added this view in the main activity's view:
<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"
tools:context="${relativePackage}.${activityClass}"
android:id="#+id/main_view">
<com.pratikthaker.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
What am I missing?

Related

CustomView with xml doesn't show up on screen

I am trying to add my custom view to the main activity's xml.
I have created the following xml for the view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Testing custom view"
android:textSize="20dp" />
</LinearLayout>
And created the following class in which the above xml is inflated:
public class TestView extends LinearLayout {
public TestView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
View.inflate(context, R.layout.test_name, null);
}
And in the xml of the main activity I have added the custom view like below:
<LinearLayout 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"
tools:context="com.example.myapplication.MainActivity">
<com.example.myapplication.TestView
android:id="#+id/submit_area"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
When I am running the app, I am getting an empty screen. It's not showing the textview which displays "Testing custom view".
Any help would much appreciated.
Thanks
Your view inflation code in your custom view looks wrong.Try it the way given below.
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.view_color_options, this, true);

Android: Adding View inflated from XML Layout to Viewgroup which has not defined any width yet

I have a layout problem with my custom viewgroup class.
I call init() in the constructor. In my init() function I inflate the viewgroups layout from an xml file, which contains a LinearLayout to which I add several other views.
I am using spacer (View layout_width="0" and layout_weight="1") to distribute the items equaly.
The problem lies here: the layout still has not defined any width when i add the children. So the spacer all have the size 0, and wont actually place the "line_dot" items equally. How can i somehow update their size?
public class SliderSwitch extends FrameLayout {
...
public SliderSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context)
{
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.slider_switch,this);
sliderLayout = (LinearLayout) findViewById(R.id.sliderLayout);
labelLayout = (LinearLayout) findViewById(R.id.labelLayout);
// add one spacer
View spacer = (View) inflate(context,R.layout.spacer, null);
sliderLayout.addView(spacer);
// setup the view depending on how many elements there are
for (int i=1;i<numberOfElements-1;i++) {
ImageView lineDot = (ImageView) inflater.inflate(R.layout.slider_switch_line_dot, null);
sliderLayout.addView(lineDot);
View spacer = (View) inflate(context,R.layout.spacer, null);
sliderLayout.addView(spacer);
}
}
...
}
this is the xml file for the spacer:
<View
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
and this is the one for my viewgroup layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/relLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/left_bg" />
<LinearLayout
android:id="#+id/sliderLayout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/middle_bg"
android:gravity="center"
android:orientation="horizontal" >
<!-- <include layout="#layout/spacer"/> -->
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/right_bg" />
</LinearLayout>
<ImageButton
android:id="#+id/sliderKnob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="0dp"
android:background="#null"
android:src="#drawable/knob" />
</RelativeLayout>
</LinearLayout>
I found the solution now. You have to set the LayoutParams in the code again (even if they are already defined in the xml file), then everything is neatly spaced, how its supposed to. seems to be a bug. But this solution works:
// add one spacer
View spacer = (View) inflate(context,R.layout.spacer, null);
spacer.setLayoutParams(new LinearLayout.LayoutParams(1,LayoutParams.WRAP_CONTENT,1.0F));
sliderLayout.addView(spacer);
// setup the view depending on how many elements there are
for (int i=1;i<numberOfElements-1;i++) {
ImageView lineDot = (ImageView) inflater.inflate(R.layout.slider_switch_line_dot, null);
sliderLayout.addView(lineDot);
spacer = (View) inflate(context,R.layout.spacer, null);
spacer.setLayoutParams(new LinearLayout.LayoutParams(1,LayoutParams.WRAP_CONTENT,1.0F));
sliderLayout.addView(spacer);
}
You can call init() on onSizeChanged callback. Remember to set and keep a flag in order to avoid calling it twice, since this callback may run more than once.

Activity with dynamicly added components freezes

My Application freezes and LogCat grows heap (frag case) to 14mb if add more then 3 own "components" to current activity/layout. It takes very long until the fourth "component" is added and Android asks to close my application.
I've written a Activity which has some components (EditTexts) and a own "component". I want to do something similar to the contacts app (Number adding) but with ingredients. So I've created a class IngredientsLayout which extends LinearLayout and a Layout xml file with a TextView and a "Add"-Button which I've placed on the Activity-Layout. Every time I press the Add Button, a single IngredientLayout with 3 EditTexts and a ImageButton will be added to the current IngredientsLayout which should "hold" all added ingredients.
What I'm doing wrong?
IngredientsLayout class:
public class IngredientsLayout extends LinearLayout {
ImageButton imageButtonAddIngredient;
ArrayList<IngredientLayout> arrayList;
public IngredientsLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.ingredients_list, this);
arrayList = new ArrayList<IngredientLayout>();
imageButtonAddIngredient = (ImageButton) findViewById(R.id.imageButtonAddIngredient);
imageButtonAddIngredient.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
LinearLayout layout = (LinearLayout) findViewById(R.id.linearLayoutIngredientsList);
IngredientLayout ingredientLayout = new IngredientLayout(getContext(), null);
ingredientLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
arrayList.add(ingredientLayout);
layout.addView(ingredientLayout);
}
});
}
}
ingredients_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayoutIngredientsList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="left|center_vertical"
android:layout_weight="1"
android:text="#string/ingredients_list_name" />
<ImageButton
android:id="#+id/imageButtonAddIngredient"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#drawable/ic_menu_add_ingredient" />
</LinearLayout>
</LinearLayout>
</merge>
IngredientLayout class:
public class IngredientLayout extends LinearLayout {
public IngredientLayout(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.ingredients_list_row, this);
}
}
ingredients_list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayoutIngredientRow"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/editTextAmount"
android:layout_width="45dp"
android:layout_height="fill_parent"
android:layout_weight="0.11"
android:ems="10"
android:hint="#string/ingredients_list_listrow_amount"
android:inputType="numberDecimal" >
<requestFocus />
</EditText>
<EditText
android:id="#+id/editTextUnit"
android:layout_width="60dp"
android:layout_height="fill_parent"
android:layout_weight="0.06"
android:ems="10"
android:hint="#string/ingredients_list_listrow_unit" /><EditText
android:id="#+id/editTextName"
android:layout_width="127dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:layout_weight="0.005"
android:ems="10"
android:hint="#string/ingredients_list_listrow_name" />
<ImageButton
android:id="#+id/imageButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:src="#drawable/ic_menu_cancel" />
</LinearLayout>
</merge>
LinearLayouts are not meant for this kind of dynamic accessing.
What you need to do is a ListView and a adapter.
And every time you add a new item into the adapter you call it's NottifyDataChanged to update the list view with the new item.

Android: Same xml acts differently depending on where I inflate it and I don't know why

Why do some views in a linearlayout within a scrollview fill the parent when fill_parent is set when inflated from xml directly but don't when added via a custom component that inflates the same xml?
The result of inflating the same xml in two different places:
The top item of the two is as a result of inflating the xml in a class that extends linearLayout and then adding that class to the linearLayout inside the scroll view. This view isn't filling the parent and I can't work out why.
The bottom item is the result of inflating the xml directly in the activity that this is all contained within. It appears as I expected.
This is the code that adds the two views in the activity:
scrollList.addView(new CommunityTaskListItem(this, null));
scrollList.addView(View.inflate(getBaseContext(), R.layout.communitytask, null));
This is the code that inflates the activity within a custom component class "CommunityTaskListItem":
View communityTask = View.inflate(context, R.layout.communitytask, null);
addView(communityTask);
I assume the xml is okay because it works fine when inflated directly in the activity. My question is why the fill_parent property seems to be lost when the xml is inflated in a custom component's class?
For good measure, here is the xml being inflated: EDIT: I gave you the wrong one before!!! Here's the right one:
<?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="wrap_content">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</LinearLayout>
I'd like to keep the custom component and not inflate the xml within my activity if I could.
EDIT: Code where CommunityTaskListItem is inflated:
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class CommunityTaskListItem extends LinearLayout {
TextView textViewCommunityTaskTimes;
TextView textViewCommunityTaskDescription;
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
View communityTask = View.inflate(context, R.layout.communitytask, null);
addView(communityTask);
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
...
EDIT: All working now! Here's the final code for anyone else incase they have a similar issue:
Contructor for the custom object:
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
addView(inflate(context, R.layout.communitytask, null));
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
Custom object xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</LinearLayout>
To be honest I don't know exactly what the mistake I was making was so if someone could make that clear I'd be very grateful.
The first line should be:
scrollList.addView(new CommunityTaskListItem(this, null)
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
You call inflate() inside CommunityTaskListItem class and inflated view becomes a child view of the CommunityTaskListItem view. But you don't set width and height for this view so it doesn't match its parent's width.
EDIT: I think your XML should look like this:
<?xml version="1.0" encoding="utf-8"?>
<packagename.CommunityTaskListItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</packagename.CommunityTaskListItem>
where packagename is the name of the package of the CommunityTaskListItem class.
In this case you should change the CommunityTaskListItem:
public class CommunityTaskListItem extends LinearLayout {
TextView textViewCommunityTaskTimes;
TextView textViewCommunityTaskDescription;
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
// ....
}
This class cannot be created using its constructor. It can be only inflated.
The second way is to inflate children in the constructor like you do. But the XML should differ:
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/linearLayout1" android:background="#drawable/plainbutton" android:layout_marginBottom="5px" android:layout_marginTop="5px" android:layout_weight="1">
<TextView android:layout_height="wrap_content" style="#style/CommunityTaskText" android:layout_width="fill_parent" android:layout_weight="1" android:id="#+id/textViewCommunityTaskTimes" android:text="xx:xx - xx:xx"></TextView>
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" style="#style/CommunityTaskText" android:id="#+id/textViewCommunityTaskDescription" android:text="Task"></TextView>
</LinearLayout>
</merge>
The CommunityTaskListItem will be:
public class CommunityTaskListItem extends LinearLayout {
TextView textViewCommunityTaskTimes;
TextView textViewCommunityTaskDescription;
public CommunityTaskListItem(Context context) {
this(context, null);
}
public CommunityTaskListItem(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
inflate(context, R.layout.communitytask);
textViewCommunityTaskTimes = (TextView)findViewById(R.id.textViewCommunityTaskTimes);
textViewCommunityTaskDescription = (TextView)findViewById(R.id.textViewCommunityTaskDescription);
}
// ....
}
This class can be created using its contructor and inflated from an XML. But if you want to inflate it, you should create a separate XML file. Let's call it task.xml.
<?xml version="1.0" encoding="utf-8"?>
<packagename.CommunityTaskListItem
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"/>
And that's how you can use it:
scrollList.addView(new CommunityTaskListItem(this),
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
scrollList.addView(View.inflate(getBaseContext(), R.layout.task, null));

How to populate a compound viewgroup extending from LinearLayout?

I am trying to create a compound viewgroup after inflating the group from an XML file.
The viewgroup is composed as: A LinearLayout Root, 2 child LinearLayouts. I am able to see the layout correctly in the layout editor; however, when I attempt to add a view (say a button) from the editor, the view does not show up and the application immediately force closes. I was told i may need to Override the onLayout method to correctly draw the view components but I'm am fairly confused.
My Class:
public class FocusBox extends LinearLayout {
private LinearLayout rootLayout,
contentLayout,
topLayout;
public FocusBox(Context context)
{
super(context, null);
}
public FocusBox(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.focus_box, this);
rootLayout = (LinearLayout)findViewById(R.id.focusBoxParent);
contentLayout = (LinearLayout)findViewById(R.id.focusBottom);
topLayout = (LinearLayout)findViewById(R.id.focusTop);
}
}
And the xml:
<?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="match_parent"
android:padding="4dp"
android:id="#+id/focusBoxParent"
android:orientation="vertical">
<LinearLayout
android:background="#drawable/gradients"
android:layout_weight=".1"
android:gravity="center"
android:id="#+id/focusTop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:text="TextView"
android:id="#+id/focusTitle"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_width="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_weight=".9"
android:id="#+id/focusBottom"
android:background="#drawable/gradient2"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
Generally, if you inflate a layout from a valid XML you shouldn't get an error. You should do a clean build and re-deploy the app again.
Also check if you're using the correct class in the import statement in other classes (you could be using a FocusBox from some 3rd-party library instead of the one you made)

Categories

Resources