Dynamically adding textviews to layout and adjusting accordingly - android

I'm adding TextViews dynamically with code. Now I'm using a LinearLayout with horizontal orientation which i thought would add a new line when the textviews doesnt fit into the row. And how wrong I was.
Thing is I don't know how many rows there will be, since it depends on user input. Therefor a GridView doesn't feels right, since I can't specify the number of columns. And I don't know every size of every TextView, which might make it look bad if a TextView is very long and I want 3 TextViews per row.
I'm sure there is a simple solution to this, I just wanna know the best one. Which layout should I use so when I add TextViews to it, so it makes a new row below the first one when it reaches the screen width?
Thanks!

See this:
package us.simpleit;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class SimpleGUI extends Activity {
TextView tv;
EditText et;
LinearLayout ll;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//LinearLayout ll = new LinearLayout(this);
ll = new LinearLayout(this);
ll.setOrientation(android.widget.LinearLayout.VERTICAL);
ll.setLayoutParams(new ViewGroup.LayoutParams(-1,-1));
// ARGB: Opaque Red
ll.setBackgroundColor(0x88ff0000);
tv = new TextView(this);
tv.setLayoutParams(new ViewGroup.LayoutParams(-1,-2));
tv.setText("sample text goes here");
// ARGB: Opaque Green
tv.setBackgroundColor(0x5500ff00);
ll.addView(tv);
et = new EditText(this);
et.setLayoutParams(new ViewGroup.LayoutParams(-1,-2));
et.setText("edit me please");
// ARGB: Solid Blue
et.setBackgroundColor(0xff0000ff);
ll.addView(et);
Button btn = new Button(this);
btn.setText("Go!");
btn.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
tv.setText(et.getText().toString());
}
});
ll.addView(btn);
setContentView(ll);
//setContentView(R.layout.main);
}
}
Here i have taken One TextView and One EditText. Instead of that you can take two TextView or any Number of view you want.
Enjoy. :)

Thing that you could do is to make your main LinearLayout with vertical orientation and many LinearLayout children with horizontal orientation
When you want to add TextView, get the last child of the main layout to know if this child can contain you new TextView. If not, then add a new LinearLayout with horizontal orientation

Related

Button drawing wrongly background after text size changed

I am putting a bunch of buttons in LinearLayout, with weight=1 for each. The problem is, that when the setTextSize gets called, it sometimes changes the space the background is drawn on (so if the new text size is smaller the one button has perceived height FE 2/3 of all the other buttons). The onSizeChanged gets never called even though the size drawn changes. The button does not change it's postion (debug by getLocationInWindow) neither it's size (getWidth, getHeight).
Am I doing something wrong, or is there at least a way to fix it?
MainActivity:
import android.app.ActionBar;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroup mainLayout = (ViewGroup)findViewById(R.id.mainLayout);
LinearLayout l = new LinearLayout(this);
mainLayout.addView(l);
for (int i = 0; i < 8; i++) {
Button b = new Button(this);
LinearLayout.LayoutParams p1 = new LinearLayout.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, 200);
p1.weight = 1;
b.setLayoutParams(p1);
b.setBackgroundColor(Color.YELLOW);
l.addView(b);
}
Button b = ((Button)l.getChildAt(7));
b.setTextSize(50f);
}
}
And for it to be all, XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="dracek.fit.cvut.cz.test.MainActivity">
</android.support.constraint.ConstraintLayout>
I tried all this for the button but no change:
requestLayout();
invalidate();
ViewParent vp = getParent();
if (vp != null)
vp.requestLayout();
So I will answer myself if noone else does so.
In the end I found out, that the LinearLayout is for whatever reason trying to have all the text baselines in the same height, thus moving the buttons. Adding one line solves the problem:
p1.gravity =Gravity.FILL;

Android - removing layout programmatically

I have an activity that makes a layout programmatically from a Shared Preference using a for loop. The text views and buttons are enclosed in a linear layout. The user can input as many views as he wants. Now, the button will be a delete button. When pressed, I want to delete the linear layout the button and the other textviews are contained. How do I do this?
HERE IS MY CODE:
package com.dirkjan.myschools;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
LinearLayout subjectLeft, subjectRight;
Button addSubj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
subjectLeft = (LinearLayout) findViewById(R.id.llSubjectLeft);
subjectRight = (LinearLayout) findViewById(R.id.llSubjectRight);
//Load the saved subjects
SharedPreferences getSubjects = getSharedPreferences("SubjectInfo_Prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = getSubjects.edit();
int subjectCount = getSubjects.getInt("count", 0);
if (subjectCount > 0 ){
for (int i = 1; i <= subjectCount; i++){
//Set the linear layout for each subject
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
float scale = getResources().getDisplayMetrics().density;
//SET BOTTOM MARGIN
float margin = 5; //RESIZE MARGIN HERE!
int margs = (int) (margin * scale + 0.5f);
//SET PADDING IN DP
float padding = 5; //RESIZE PADDING HERE!
int pads = (int) (padding * scale +0.5f);
llParams.setMargins(0,0,0,margs);
//SETTING THE LINEARLAYOUT PARAMS
ll.setLayoutParams(llParams);
ll.setPadding(pads, pads, pads, pads);
//SETTING THE BACKGROUND COLOR OF THE LINEAR LAYOUT
String chosenColor = getSubjects.getString("chosenColor" + i, "BLUE");
if (chosenColor.equals("Green")){
ll.setBackgroundResource(R.color.HoloGreen);
}else if (chosenColor.equals("Blue")){
ll.setBackgroundResource(R.color.HoloBlue);
}else if (chosenColor.equals("Gray")){
ll.setBackgroundResource(R.color.HoloGray);
}else if (chosenColor.equals("Orange")){
ll.setBackgroundResource(R.color.HoloOrange);
}else {
ll.setBackgroundResource(R.color.HoloYellow);
}
//ADDING THE LAYOUT TO THE APPROPRIATE CONTAINER (LEFT OR RIGHT)
if (i % 2 == 1){
subjectLeft.addView(ll);
} else {
subjectRight.addView(ll);
}
//SETTING THE SUBJECT NAME TEXTVIEW
TextView SubjectName = new TextView(this);
SubjectName.setText(getSubjects.getString("subjectName" + i, "Error"));
SubjectName.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
SubjectName.setTextSize(22);
SubjectName.setTypeface(Typeface.DEFAULT_BOLD);
//SETTING THE SUBJECT NUMB TEXT VIEW
TextView SubjectNumber = new TextView(this);
SubjectNumber.setText(getSubjects.getString("subjectNumb" + i, "Error"));
SubjectNumber.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
SubjectNumber.setTextSize(16);
//Creating the divider line
ImageView divider = new ImageView(this);
LinearLayout.LayoutParams dividerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 2);
divider.setLayoutParams(dividerParams);
divider.setBackgroundResource(R.color.Black);
//Add Views into the Layout
ll.addView(SubjectNumber);
ll.addView(SubjectName);
ll.addView(divider);
}
}
addSubj = (Button) findViewById(R.id.buttonPlusSubject);
addSubj.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent toAddSubj = new Intent(MainActivity.this,
AddSubjectActivity.class);
startActivity(toAddSubj);
finish();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Please do take note that no id is assigned for each layout. It would help if there is a code to identify the parent of the parent of the button (The button is in a relative layout, which is in a linear layout where the linear layout must be removed by clicking the button.
First find your parent layout using
ll = (LinearLayout) findViewById(R.id.main_linearlayout);
get the child layout using
final LinearLayout child = (LinearLayout) ll.findViewById(count);
now to remove the whole layout you can use removeview() method as below
ll.removeView(child);
to only remove all views from the particular layout(here for eg. child) you can use
child.removeAllViews();
You can call view.setVisiblility(View.GONE) if you want to remove it from the layout, or view.setVisibility(View.INVISIBLE) if you just want to hide it.
You can remove a Child View from a parent by calling removeView(View view), for example like this :
parent.removeView(child);
Supposing that your LinearLayout ID is my_linear_layout, just do this in your onClickListener:
findViewById(R.id.my_linear_layout).setVisibility(View.GONE);
In your XML, be sure to put the ID:
<LinearLayout
android:id="#+id/my_linear_layout"
...>
</LinearLayout>
you can do this like get the id of the currently clicked item
and assigned in root layout
LinearLayout layout = (LinearLayout) v.getParent();
And remove using this code given below:
linearLayout.removeView(layout);

Drawing shapes programmatically for Android

I'm new to the Android SDK so I'm trying to figure this out. I have read the documentation and a text book and they haven't been particularly helpful in this matter.
I'm just trying to draw a simple rectangle in a linear layout on the screen. I can't get the shape to show up, however, when I add text to this layout in the same fashion, the text does show up. What am I missing?
package jorge.jorge.jorge;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class ShapesActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ShapeDrawable rect = new ShapeDrawable(new RectShape());
rect.getPaint().setColor(Color.GREEN);
ImageView view1 = new ImageView(this);
view1.setImageDrawable(rect);
LinearLayout frame = (LinearLayout)findViewById(R.id.linear1);
frame.addView(view1);
// TextView tx = new TextView(this);
//
// tx.setText("Hello World");
//
// frame.addView(tx);
}
}
The Shape is usually used for making a background to some View. Its width and height is the same of the view that is using it. Then, if this view has no width and height, It'll have no width and height, too.
Basically, I think that your ImageView has no width and height, then it's invisible.
You can see how to set it programatically here:
Set ImageView width and height programmatically?
But, I recomend you to make the layout in XML's way.

Android layouts, how to make two items in a line

I am beginner in android. And i could not understand differences between layouts. i want to make a button and next to button i want to set an image. So which layout should i have yo use and how can i set the positions.(Programitacilly)
You need to visit this page:
Common Layout Objects
You will want to use the LinearLayout - inside the linear layout you can place your button and image.
There's a good tutorial on how to use LinearLayout over here:
Android Developers-LinearLayout
If you are new to Android, I would recommend checking out the other "Hello *" tutorials over there.
Cemal wanted to see this done programatically. The above references are good for showing the XML versions. Here is a quick example of the button and image in a linear layout done entirely programtically.
package com.example.android.ProgramLinearActivity;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class ProgramLinearActivity extends Activity {
private static final int HORIZONTAL = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(HORIZONTAL); //HORIZONTAL is default but here for clarity
ImageView imageView = new ImageView(this);
imageView.setImageResource( R.drawable.icon);
Button button = new Button (this);
button.setText("Test");
linearLayout.addView(button);
linearLayout.addView(imageView);
setContentView(linearLayout);
}
}
Hit ctrl+space a lot in the eclipse editor to see tutorials on the other attributes for the button and imageview wigets.

Problems vertically aligning a Button and horizontally oriented LinearLayout within a vertcally oriented LinearLayout

Im posting from my phone so please excuse stupid typos and formatting issues.
I have an activity which lists saved games that the player can load.
I created a simple layout xml file which defines a ScrollView. On load, I grab all the saved games and programatically add a view for each saved game to a vertically oriented LinearLayout child of the ScrollView.
The view for each game consists of a Horizontally oriented LinearLayout which in turn contains a Button and a vertically oriented LinearLayout. That LinearLayout in turn contains some TextViews and ImageViews (and one more LinearLayout which I'm ommitting here for the sake of clarity).
The hierarchy looks something like this (some details omitted).
ScrollView
LinearLayout - vertical
Each saved game:
LinearLayout - horizontal
Button - load game
LinearLayout - vertical
TextView - game name
TextView - date string
My problem:
I would like the top of the button and the "game name" texview to be vertically aligned but the TextView (or maybe it's LinearLayout parent) has some rogue padding on top that I can't get rid of. See screenshot for details.
LoadSaved class:
Note: mScrollView is badly named. It refers to the ScrollView's child LinearLayout.
public class LoadSaved extends Activity {
public LinearLayout mScrollView;
private MinerDb mDb;
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.loadsaved);
mDb = new MinerDb(this);
mScrollView = (LinearLayout) findViewById(R.id.load_scroll_view);
Bundle[] savedGames = mDb.getSavedGames();
for (int i = 0; i < savedGames.length; i++) {
Bundle game = savedGames[i];
final int gameId = game.getInt("gameId");
String name = game.getString("name");
String date = game.getString("date");
Bundle player = game.getBundle("player");
int playerMoney = player.getInt("money");
int playerHealth = player.getInt("health");
LinearLayout gameContainer = new LinearLayout(getApplicationContext());
gameContainer.setPadding(5, 5, 5, 5);
gameContainer.setGravity(Gravity.TOP);
gameContainer.setOrientation(LinearLayout.HORIZONTAL);
gameContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
Button loadButton = new Button(getApplicationContext());
loadButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
loadButton.setText("Load");
LinearLayout gameInfo = new LinearLayout(getApplicationContext());
gameInfo.setOrientation(LinearLayout.VERTICAL);
gameInfo.setPadding(10,0,10,10);
gameInfo.setGravity(Gravity.TOP);
gameInfo.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
TextView nameView = new TextView(getApplicationContext());
nameView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
nameView.setGravity(Gravity.TOP);
nameView.setText(name);
TextView dateView = new TextView(getApplicationContext());
dateView.setPadding(5,0,0,0);
dateView.setGravity(Gravity.TOP);
dateView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
dateView.setText(date);
LinearLayout playerView = new LinearLayout(getApplicationContext());
playerView.setOrientation(LinearLayout.HORIZONTAL);
playerView.setPadding(5,0,0,0);
playerView.setGravity(Gravity.TOP);
playerView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
TextView playerMoneyView = new TextView(getApplicationContext());
playerMoneyView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
playerMoneyView.setPadding(0,0,10,0);
playerMoneyView.setTextColor(Color.GREEN);
playerMoneyView.setText("$" + playerMoney);
TextView playerHealthView = new TextView(getApplicationContext());
playerHealthView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
playerHealthView.setPadding(0,0,10,0);
playerHealthView.setTextColor(Color.RED);
playerHealthView.setText(playerHealth + "%");
playerView.addView(playerMoneyView);
playerView.addView(playerHealthView);
gameInfo.addView(nameView);
gameInfo.addView(dateView);
gameInfo.addView(playerView);
gameContainer.addView(loadButton);
gameContainer.addView(gameInfo);
mScrollView.addView(gameContainer);
loadButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.e("LoadSaved", "LoadSaved::onCreate: Clicking: " + gameId);
Intent loadGameIntent = new Intent(LoadSaved.this, Miner.class);
loadGameIntent.putExtra("load_game", gameId);
startActivity(loadGameIntent);
finish();
}
});
}
}
}
loadsaved.xml
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/load_scroll_view" />
</ScrollView>
</LinearLayout>
If you want any kind of alignment, why don't you use a RelativeLayout? That's basically designed to align one view with another. android:layout_alignTop sounds like something you want.
(And, of course, verify that the padding values are the same in all controls, but I'm sure you did that.)
Why don't you try using a ListView for that kind of gui.
You will still need to define a row xml.
+1 to the answers suggesting ListView and RelativeLayout. For this type of situation you probably want a ListView with an item layout using RelativeLayout. (ListView will scale much better if there are many items, and if this is for a list of saved games it seems like this could grow quite a bit.) For this type of UI it's recommended to have the whole row/list item clickable rather than use a small Load button, but that's a design issue and ultimately up to you.
Don't use getApplicationContext for creating your views. Activity is a Context, just pass this in your case.
By default LinearLayouts try to align child views by their text baseline if present. Note that the bottom of your button's Load text aligns perfectly with the CURRENT_GAME text in your screenshot. Try gameContainer.setBaselineAligned(false).
Normally your gameInfo layout would only report the baseline of one of its children if you set a baselineAlignedChildIndex, but it looks like this behavior changed between cupcake and eclair when creating LinearLayouts programmatically. (Link to the commit that changed it in AOSP here.)

Categories

Resources