I am using linear layout to get the message with image from .net server.
when the new message is come the position of the layout is increased and the new message is added to the top of the layout one by one.
the problem is when the new message will come,the new message is added to layout suddenly.
I want to apply animation to the layout and make my app like when the new message is come the message is added to the layout slowly. means the previous messages move down slowly and new message is added top of the layout.
Use android:animateLayoutChanges on the LinearLayout that shall hold the data. This will trigger an animation when adding new content. It starts by moving the old data down making room for more content. Then follows a second step where the new data will fade into the free space.
Example code
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/baseLL"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- button used to add data -->
<Button
android:layout_width="192dip"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Add Content"
android:onClick="onAddContentClick" />
<!-- button used to remove data -->
<Button
android:layout_width="192dip"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Remove Content"
android:onClick="onRemoveContentClick" />
<!-- data will be added to this LinearLayout at run time -->
<LinearLayout
android:id="#+id/dataLL"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:animateLayoutChanges="true"
>
</LinearLayout>
</LinearLayout>
basicanimation.java
package com.test.animation.basic;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
public class BasicAnimationActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onAddContentClick(View v) {
LinearLayout dataLL = (LinearLayout) findViewById(R.id.dataLL);
int dataCount = dataLL.getChildCount();
TextView newDataTV = generateData(dataCount);
dataLL.addView(newDataTV, 0);
}
public void onRemoveContentClick(View v) {
LinearLayout dataLL = (LinearLayout) findViewById(R.id.dataLL);
if (dataLL.getChildCount() > 0) {
dataLL.removeViewAt(0);
}
}
private TextView generateData(int dataCount) {
TextView TV = new TextView(this);
TV.setText("Data " + dataCount);
TV.setLayoutParams(new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT,
android.view.ViewGroup.LayoutParams.WRAP_CONTENT));
return TV;
}
}
Related
I am new to Android Studio/Development, but not programming itself. I am struggling with the syntax (as I do think it is my problem) yet I cannot find a solution anywhere on here or on Google. I have this 2nd activity named FilterActivity. FilterActivity currently has 2 TextViews. Both create dynamic CheckBoxes. Right now, I only have one doing this so I can get one right before I go onto another. Here's the issue, I click on the TextView to get the dynamically created CheckBox and it shows perfectly fine. However, clicking on it again just adds the same values until it appears to completely fill the parent via xml.
No matter what I search, what I do, it all does the same exact thing. I know, I have nothing for onCheckedChanged, but I have previously before and it did not work either. So question(s), should I not be using LinearLayout and do like a container of sorts? There will be a decently big database for the checkboxes (500+) so I was thinking I would have to implement ScrollView at some point. Also, if LinearLayout is the correct way to go, what am I doing wrong? I am just completely spinning and I know it should not be this hard.
Thank you to anyone that gives feedback!
Here's XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="xxx.AppEx.FilterActivity"
tools:layout_editor_absoluteY="81dp"
tools:showIn="#layout/activity_filter">
<View
android:id="#+id/firstView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerHorizontal="true" />
<View
android:id="#+id/secondView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerVertical="true"/>
<TextView
android:id="#+id/AllTextView"
android:clickable="true"
android:text="All"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:height="50dp"
android:layout_toLeftOf="#id/firstView"
android:layout_alignParentTop="true"
android:gravity="center"
android:textStyle="bold"
android:textAllCaps="true"/>
<TextView
android:id="#+id/DisTextView"
android:clickable="true"
android:text="Dis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:height="50dp"
android:layout_toRightOf="#+id/firstView"
android:layout_alignParentTop="true"
android:gravity="center"
android:textStyle="bold"
android:textAllCaps="true"/>
<LinearLayout
android:id="#+id/CheckBoxLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="#id/secondView">
</LinearLayout>
</RelativeLayout>
Here's the main code:
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.content.Intent;
public class FilterActivity extends AppCompatActivity implements
CompoundButton.OnCheckedChangeListener {
LinearLayout CheckBoxLayout;
CheckBox checkBox;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_filter);
CheckBoxLayout = (LinearLayout) findViewById(R.id.CheckBoxLayout);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final TextView AllTextView = (TextView) findViewById(R.id.AllTextView);
AllTextView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
AllTextView.setBackgroundColor(Color.BLUE);
onAllClick();
}
});
TextView DisTextView = (TextView) findViewById(R.id.DisTextView);
DisTextView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//onAllClick();
}
});
}
public void onAllClick()
{
Intent intent = getIntent();
dummy();
}
public void dummy()
{
String[] array = new String[]
{
"Rice", "Beans"
};
LinearLayout CheckBoxLayout = (LinearLayout)findViewById(R.id.CheckBoxLayout);
for (int i = 0; i < array.length; i++)
{
CheckBox checkBox = new CheckBox(this);
checkBox.setText(array[i]);
CheckBoxLayout.addView(checkBox);
}
}
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
}
}
i'm trying to create a widget called DecoView dynamicaly every time i press a button.
if i just put two deco views in the XML i can see them both and they both look fine on ontop of the other.
but when i try to add it dynamicly in the code, i only create the first one,
and all the rest just aren't get created
what am i missing here ?
can someone help me with this ?
my mainActivity.java
package com.example.shay_v.dynamicdecoviewexample;
import android.graphics.Color;
import android.graphics.PointF;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.hookedonplay.decoviewlib.DecoView;
import com.hookedonplay.decoviewlib.charts.SeriesItem;
import com.hookedonplay.decoviewlib.events.DecoEvent;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
Button mainMenuButton;
int widgetInteger = 1;
LinearLayout ll;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//pointing to display
mainMenuButton = (Button) findViewById(R.id.button);
mainMenuButton.setOnClickListener(this);
//points to the linear layout in the xml
ll = (LinearLayout)findViewById(R.id.mainMenu_mainLayout);
}
private void createDecoViewWidget (int i) {
//adds params to the linear layout
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
//deco view widget
DecoView decoViewWidget = new DecoView(this);
//adding to view
decoViewWidget.setId(i);
ll.addView(decoViewWidget, params);
//decoViewWidget.configureAngles((int) (Math.random() * 360) + 1, (int) (Math.random() * 100));
//Create data series track
SeriesItem seriesItem = new SeriesItem.Builder(Color.argb(255, (int) (Math.random()*255), (int) (Math.random()*255), (int) (Math.random()*255)))
//third controller is end point
.setRange(0, 100, 0)
.setLineWidth(60f)
.setInset(new PointF(120f, 120f))
.build();
int series1Index = decoViewWidget.addSeries(seriesItem);
decoViewWidget.addEvent(new DecoEvent.Builder((float) (Math.random() * 100)).setIndex(series1Index).setDelay(1000).build());
}
//button listener
#Override
public void onClick(View v) {
createDecoViewWidget (widgetInteger);
widgetInteger++;
}
}
my activity_main.xml >
<?xml version="1.0" encoding="utf-8"?>
<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="com.example.shay_v.dynamicdecoviewexample.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<LinearLayout
android:orientation="vertical"
android:layout_width="350dp"
android:layout_height="350dp"
android:layout_centerVertical="true"
android:id="#+id/mainMenu_mainLayout"
android:layout_centerHorizontal="true"></LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
anyone ?
When you are creating the Views they are being added into a LinearLayout. This type of layout will position the views one after the other, so the second view is being drawn off the visible area of the screen.
As you want all views to be drawn on top of each other you should use a RelativeLayout.
I'm relatively new to android development and I'm trying to find a way to inflate a view repeatedly each time when a button is pressed, in a different location, so every inflated view has its own position:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class teamCreateScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.team_locate_layout);
}
public void createTeam(View view) {
final RelativeLayout rlTeam = (RelativeLayout) findViewById(R.id.rlTeam);
View teamBox = View.inflate(this, R.layout.team_box, rlTeam);
final TextView teamBoxView = (TextView) findViewById(R.id.team_task_box);
teamBoxView.setX(0);
teamBoxView.setY(230);
}
}
The XML code of the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/rlTeam">
<Button
android:layout_width="60dp"
android:layout_height="60dp"
android:id="#+id/teamAddBtn"
android:text="+"
android:textSize="30sp"
android:onClick="createTeam"/>
</RelativeLayout>
XML code of the view that's being inflated:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="192dp"
android:layout_height="120dp"
android:id="#+id/team_task_box"
android:text="New Team" />
</RelativeLayout>
I want to use the same view to inflate multiple boxes with different coordinates in the layout. Every time I press the button to inflate the view again it inflates the box in the same coordinates so they overlap. I need to make the second box to appear to the first one's right, the third below 1st and so on, much like a grid of boxes.
Try this code and tell me whether it works. Remove the inflating of layout
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class teamCreateScreen extends Activity {
int i=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.team_locate_layout);
}
public void createTeam(View view) {
final RelativeLayout rlTeam = (RelativeLayout) findViewById(R.id.rlTeam);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
TextView tv=new TextView(getApplicationContext());
if(tv.getId()>0) {
relativeParams.addRule(RelativeLayout.BELOW, tv.getId());
}
tv.setId(i);
r1Team.addView(tv, relativeParams);
i++;
}
}
Declare int i=0; as a global variable and increment it in the createTeam() method.
First of all, I wanna say I've been seeking for an answer on the Forum and I found didn't match for what I wanted. Basically, what I want is: when the user clicks on one of the images previously "specified" on the .xml file, a new image is displayed on the center of the screen that is not "specified" on the .xml file. I wrote "specified" cause idk if it's the correct way to refer to this.
EDIT: there was no need to not specify the image previously, all I needed was to set "gone" for visibiity. This code is working exactly how I wanted (ty guys):
Main.java
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.Toast;
public class Principal extends Activity {
ImageView cuia1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_principal);
cuia1 = (ImageView) findViewById(R.id.cuia1);
cuia1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
ImageView cuia1grande = (ImageView) findViewById(R.id.cuia1grande);
cuia1grande.setVisibility(1);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.principal, menu);
return true;
}
}
activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:id="#+id/tableLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:shrinkColumns="*"
android:stretchColumns="*">
<TableRow
android:id="#+id/tabelaCuias"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:gravity="center">
<TextView
android:id="#+id/selecionaCuia"
android:text="Selecione a cuia"
android:textStyle="bold">
</TextView>
<ImageView
android:id="#+id/cuia1"
android:src="#drawable/cuia1">
</ImageView>
<ImageView
android:id="#+id/cuia2"
android:src="#drawable/cuia2">
</ImageView>
<ImageView
android:id="#+id/cuia3"
android:src="#drawable/cuia3">
</ImageView>
<ImageView
android:id="#+id/cuia4"
android:src="#drawable/cuia4">
</ImageView>
</TableRow>
</TableLayout>
<ImageView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_centerInParent="true"
android:visibility="gone"
android:id="#+id/cuia1grande"
android:src="#drawable/cuia1grande">
</ImageView>
Is there any reason you don't want to "specify" the image in your layout file? You could place it there and not display it (visibilty="gone"), and then show/hide it when you deem fit.
Here's what I'd do:
Make your layout a RelativeLayout instead of a TableLayout (this will make things easier for showing the image in the center)
Place your TableLayout within the wrapping RelativeLayout
Define an ImageView as the last child within the wrapping RelativeLayout, set centerInParent="true", visibilty="gone"
In your onClick method, simply set its visibility as visible.
If you really don't want to define the ImageView in the layout, then you can create it programmatically:
Follow the same steps 1-2 as before
Capture the reference to the wrapping RelativeLayout in the code
In the onClick method, create the ImageView programatically, specifying the centerInParent="true" via the code (let me know if you want an example on how to do this & I'll edit the answer with a code sample).
Add the new view to the RelativeLayout via myRelativeLayout.addView(myImageView);
Hope this helps :)
public class Principal extends Activity {
ImageView cuia1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_principal);
cuia1 = (ImageView) findViewById(R.id.cuia1);
//set invisible
cuia1 .setVisibility(View.INVISIBLE);
cuia1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//show image on the center of screen
//set image
cuia1.setImageResource(R.drawable.cuia1);
// set visible
cuia1 .setVisibility(View.VISIBLE);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.principal, menu);
return true;
}
}
import import android.view.View;
Cheerz!
I want to have a dynamic table, with rows added over time as a result of user interaction, using a TableLayout inside a ScrollView. This works fine, but when I want to scroll to the end of the table using fullScroll(), it always leaves out the last line; that is, it scrolls so that the one before the last one is visible. The last line is visible when scrolling manually, and the scrollbar is correct too.
I'm of course open to suggestions as to how to make a better layout out of this; but I'm specifically interested in understanding why fullScroll() behaves that way. Should I give it a different parameter, or use something else altogether? Or does it do that because the newly added line isn't yet visible somehow? (if so, how can I solve that?) Or did I miss some other obvious thing?
The following code replicates the problem:
TestActivity.java:
package com.example.android.tests;
import java.util.Random;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.AddRow)).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Random rnd = new Random();
TableRow nr = new TableRow(v.getContext());
for (int c=0; c<3; c++) {
TextView nv = new TextView(v.getContext());
nv.setText(Integer.toString(rnd.nextInt(20)-10));
nr.addView(nv);
}
((TableLayout) findViewById(R.id.Table)).addView(nr);
// Scrolls to line before last - why?
((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN);
}
});
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:text="Add Row"
android:id="#+id/AddRow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<ScrollView
android:id="#+id/TableScroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#id/AddRow"
android:layout_alignParentTop="true" >
<TableLayout
android:id="#+id/Table"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="0,1,2" />
</ScrollView>
</RelativeLayout>
Edit: for reference, I implemented Romain Guy's solution as follows:
In TestActivity.java, replace:
// Scrolls to line before last - why?
((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN);
with:
// Enqueue the scrolling to happen after the new row has been layout
((ScrollView) findViewById(R.id.TableScroller)).post(new Runnable() {
public void run() {
((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN);
}
});
Which works fine.
At the time you are doing your fullScroll() the layout has not happened yet, so the ScrollView uses the "old" size for the table. Instead of calling fullScroll() right away, use View.post(Runnable).
Finding the hint above useful, here is a simple implementation that scrolls a ScrollView to make a given child visible...
a: Prepare the following helper class
public class ScrollToTrick implements Runnable {
ScrollView scroller;
View child;
ScrollToTrick(ScrollView scroller, View child) {
this.scroller=scroller;
this.child=child;
}
public void run() {
scroller.scrollTo(0, child.getTop());
}
}
b) call it like this
my_scroller.post(new ScrollToTrick(my_scroller,child_to_scroll_to) );