Android setLayoutParams not working on API16 - android

I'm adding buttons to a TableLayout (TableRow) and I want to have 10 buttons tops per row but when using API16(maybe all API10 > but i didn't test for that) it just cuts out after 5 buttons (too large I assumed, that's why I tried wrap_content on them, also tried to pad to 1,1,1,1 and it worked on the API 10 making them very small but nothing happend on API16) this occurs on the emulator and my device too.
This is the result I want: http://img10.imageshack.us/img10/2243/fe32.png (API10)
This is the result I get: http://i.imgur.com/VpH8Hu1.png (API16)
java:
public class Keyboard extends Activity implements OnClickListener{
TableLayout TblLayout;
TableRow tr;
String[] numRow = {"0","1","2","3","4","5","6","7","8","9"};
String[] engKeys = {"q","w","e","r","t","y","u","i","o","p","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_keyboard);
TblLayout = (TableLayout) findViewById(R.id.tblLayout);
createRows(numRow);
createRows(engKeys);
}
public void createRows(String[] keyValues){
int i = 0;
while (i < keyValues.length) {
if (i % keyValues.length == 0 || i % 10 == 0) {
tr = new TableRow(this);
TblLayout.addView(tr);
tr.setLayoutParams(new TableRow.LayoutParams(
TableRow.LayoutParams.WRAP_CONTENT,TableRow.LayoutParams.WRAP_CONTENT));
}
Button btn = new Button(this);
btn.setText(keyValues[i]);
btn.setGravity(1);
btn.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT ,TableRow.LayoutParams.WRAP_CONTENT));
btn.setId(i);
btn.setBackgroundColor(0xFFFFFF);
btn.setOnClickListener(this);
tr.addView(btn);
i++;
}
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
xml:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/tblLayout"
>
</TableLayout>

One solution is to use LinearLayout with weightSum attribute
How to set Table width and number of Columns in TableLayout in Android
If you set android:weightSum="1" and use android:layout_weight="0.1" for each Button it will work in all devices, however it's very possible that text can get cropped. To avoid cropping, you need to dynamically calculate available width and determine how many rows you can insert that every Button text is fully visible.

Nevermind, found the problem, had to add the button into the TableRow before changing it's properties.

This is not direct answer to this question but explanation why setLayoutParams behaves differently depending on api version.
if you compare setLayoutParams implementation in api 17 and 16 you will notice one difference which is resolveLayoutParams(); that used in api 17 as opposed to older versions. that method does the trick up setting most recent layout params. So if you want your setLayoutParams work same way in all apis make sure you call it after onMeasure()

Related

"Inteligent" resize on layout?

I'm having an issue working with layouts, I've a linear layout (could be a relative layout or a table layout) which will contain an undefined number of buttons when the activity is loaded. This means, the quantity of buttons will be determined when the activity is being created. The thing is, I'm trying to fit them all in one line (with a center gravity) without changing each buttons' width UNTIL one of them reaches the margin of the screen. In other words, I want the buttons JUST to resize when at least one of them reaches the margin of the screen. That is because, I can't determine the space they're going to use because they are not created.
My actual linear layout:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="40dp"
android:id="#+id/linearLayout_1"
android:layout_above="#+id/linearLayout_2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginBottom="30dp"
android:orientation="horizontal"
android:gravity="center"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true">
</LinearLayout>
Piece of code that creates the buttons:
protected void hacerVisiblesRespuesta(){
ViewGroup linearLayout = (ViewGroup) findViewById(R.id.linearLayout);
assert linearLayout != null;
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,40, getResources().getDisplayMetrics());
for(int i = 0; i < longuitudPalabra; i++){
String boton = "btn_rsp" + Integer.toString(i+1);
Button bt = new Button(this);
bt.setText("");
bt.setId(getResourceId(boton,"id",getPackageName()));
bt.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT
, height
, 1.0f));
bt.setTextColor(Color.BLACK);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
clickBotonRespuesta(v);
}
});
bt.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bt.setBackground(getDrawable(R.drawable.bgbtnrsp));
}else{
//bt.setBackgroundDrawable(getDrawable(R.drawable.bgbtnrsp));
}
bt.setTextSize(20);
Typeface typeFace= Typeface.createFromAsset(getAssets(),"fonts/Montserrat-Regular.ttf");
bt.setTypeface(typeFace);
linearLayout.addView(bt);
}
}
I've tried many things, one of them was to make the buttons' width variable with weight property. The thing is if there are a small quantity of buttons, lets say 4, their width ended up enormous. Is there any way to achieve this through code? Thanks.
have you tried this?
button.setLayoutParams (new LayoutParams(50, LayoutParams.WRAP_CONTENT)

Setting Some TextView's Text

In my Project , I have 80 TextViews.
I should set their text from 1 to 80 once project runs , and they dont need to be changed in future.
Except TxtViews , I have some other things in my Layout, the TextViews are under ImagesViews. actually I have 80 imagesViews and under them are 80 TextViews. I want to set text of textViews from 1 to 80 dynamically.
I know I can do it in my layout.xml ,
but its really time consuming.
is there any way to do that by code?
for example with a for cycle or something like that?
Create a ViewGroup suitable for your needs in the layout, for example:
<LinearLayout
android:id="#+id/linear_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
Then you create you TextView instances programatically, and add them to the LinearLayout, like this:
LinearLayout layout = (LinearLayout)findViewById(R.id.linear_layout);
for(int i = 0; i < 80; i++) {
TextView textView = new TextView(getContext());
textView.setText("text" + i);
layout.addView(textView);
}
Optionally, you can add tags or whatever to locate them again. Alternatively just iterate over the layouts subviews.
If you know that 80 Textview fixed then you should take listview for that.
Listview Benefit
Memory management automatically
Listview manage indexing
If they share the same layout, except for the text, and could be displayed as a list, you could use an ArrayAdapter and pass the values from code.
http://www.mkyong.com/android/android-listview-example/
Checkout the below example,
public class MainActivity extends Activity {
LinearLayout linearLayout ;
ScrollView scrollView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scrollView = (HorizontalScrollView) findViewById(R.id.scrollViewActivityMain);
}
private void populateTextViews() {
linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
//add all textViews here
for(int i=0; i < 80; i++){
TextView myTextView = new TextView(this);
myTextView.setText("My TextView "+i);
myTextView.setGravity(Gravity.CENTER);
linearLayout.addView(myTextView);
}
scrollView.addView(linearLayout);
}
}
Don't forget to put that scrollView in your xml.
Let me know if it works for you...
If your TextViews are declared on the xml, wrap them on another view so you can reference it on the java code later, then simply use a for.
Something like:
View view = findViewById(R.id.your_wrapper);
for(int i=0; i<((ViewGroup)view).getChildCount(); i++) {
View nChild = ((ViewGroup)view).getChildAt(i);
TextView tv = (TextView) nChild;
tv.setText(String.valueOf(i + 1));
}
If not, you can simply create them dynamically inside your java code, and append them to a layout like LinearLayout.
Example:
xml
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/linear"
/>
Java code
LinearLayout ll = (LinearLayout) findViewById(R.id.linear);
for (int i = 1; i <= 80; i++) {
TextView tv = new TextView(this); // Assuming you're inside an Activity.
int count = ll.getChildCount();
tv.setText(String.valueOf(i));
ll.addView(tv, count, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
}
EDIT: But truly, you should use RecyclerView or ListView for that if your values are not going to change.
You can read more about RecyclerView here, and on ListView here.
Second edit: From what you're saying on your comments, you REALLY should be using ListView instead of your current design. The solutions above and from the other answers won't work at all for your problem.

Rows of buttons with LinearLayout

I need to place a dinamic number of buttons in some rows. The number of buttons per row and the size should fit to any screen width.
LinearLayout llh = new LinearLayout(this);
llh.setOrientation(LinearLayout.HORIZONTAL);
for(int i=1; i<=nl; ++i) {
Button b = new Button(this);
b.setText(String.valueOf(i));
if(i>ul) {
b.setFocusable(false);
b.setEnabled(false);
}
llh.addView(b);
}
The problem with this piece of code is that for example, my nl test value is 10, and this only displays 6 buttons, all in the same row, and the last one is smaller than the others.
I need them to stack vertically, like, when there's no space for another button, a new row is created and the rest of the buttons go in there.
Thanks in advance.
Sounds like you are talking about a vertical FlowLayout, where newly added views are stacked vertically until there is no more room, then a new column is started.
Unfortunately Android does not already have a FlowLayout, but you can make your own. Check out this answer by Romain Guy "How can I do something like a FlowLayout in Android?", and watch the video of his talk where he describes how to create one. I learnt a great deal about creating custom layouts by watching this several times until I understood it.
If the width of the screen is less than a certain value, set the weight property to 1 for all buttons. And if the screen width is large enough to fit all your buttons properly, go with the default.
I cannot post the code now as I am far away from my PC.
This is what I came up with. It's not as pretty as I tought but it gets the job done.
Buttons will have fixed size, but that shouldn't be much of a problem.
Thanks for all your help :)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top|center_horizontal"
android:orientation="vertical"></LinearLayout>
Display display = getWindowManager().getDefaultDisplay();
Point p = new Point();
display.getSize(p);
int buttonSize = 120;
int n = p.x/buttonSize-1;
LinearLayout llv = (LinearLayout)findViewById(R.id.container);
LinearLayout llh = null;
for(int i=0; i<nl; ++i) {
Button b = new Button(this);
if(i%n==0 || i==0) {
llh = new LinearLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
llh.setLayoutParams(params);
llh.setOrientation(LinearLayout.HORIZONTAL);
llv.addView(llh);
}
b.setText(String.valueOf(i+1));
b.setWidth(buttonSize);
if(i>ul) {
b.setFocusable(false);
b.setEnabled(false);
}
llh.addView(b);
}

How to add Buttons dynamically into ScrollView

I'm having a difficulty adding buttons dynamically to a ScrollView. The code below is adding the buttons BUT there is no scroller.
If I'm putting the buttons directly in the XML (not dynamically) it's working and I can scroll down/up.
My view:
<ScrollView android:id="#+id/ScrollView01"
android:layout_width="264dp"
android:layout_height="match_parent"
android:fillViewport="true"
>
<LinearLayout
android:id="#+id/buttons"
android:layout_width="264dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:scrollbars="vertical"
>
** HERE THE BUTTONS SHOULD BE ADDED DYNAMICALLY **
</LinearLayout>
</ScrollView>
The code which adding buttons:
// create new button
final Button newbutton = new Button(this);
// set background color
newbutton.setBackgroundColor(Color.GRAY);
// set width and height
newbutton.setWidth(50);
newbutton.setHeight(20);
// set position
newbutton.setY(((float)numOfButton*20)+20);
newbutton.setX(100);
// set text
newbutton.setText(Integer.toString(numOfButton));
// create patameter
final LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT
);
//set listener
android.view.View.OnClickListener buttonListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// make all the DrawView invisible
for(View view : comments){
view.setVisibility(View.INVISIBLE);
}
// set the chosen comment visible
comments.get(numOfButton).setVisibility(View.VISIBLE);
boardsHandler.setCurrenBoard(numOfButton);
}};
newbutton.setOnClickListener(buttonListener);
// creating a thread to add button
buttons.post(new Runnable() {
#Override
public void run() {
buttons.addView(newbutton, p);
}
});
Is it something with the LinearLayout.LayoutParams p ?
Thanks!
Try following code
first do
LinearLayout myContainer = findViewById(R.id.layoutId);
When you set parameters for a view, they need to correspond to the parent view for your widget.
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.FILL_PARENT);
finally add button as you are doing.
try and tell if it works
Setting X and Y position will not work. The LinearLayout layouts it's children vertically or horizontally, only taking their width/height into account.
Besides this -- have you tried calling buttons.invalidate() after buttons.addView(...). This should refresh the layout and should show your newbutton.
This is a rather old post but I found it quickly when doing research on that kind of problem. So I'll post am answer anyway, maybe it'll be of help to anyone..
I had a similar problem with a relative layout to which buttons were added dynamically. I found a workaround in defining the layout's size manually when adding the buttons. For your case, adding the line
buttons.getLayoutParams().height = numOfButton*20+40;
after
buttons.addView(newbutton, p);
might help, though it's probably not the best solution.
I thought my mistake was using the RelativeLayout at all, but since you appear to have the same problem...
Ever thought of using a table layout?

Nesting layouts and dynamically updating them

I want to nest a TableLayout inside a RelativeLayout and later dynamically edit the TableLayout in my Java Code.
My XML-File looks like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_load_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LoadDateActivity" >
<!-- few buttons and textviews -->
<TableLayout
android:id="#+id/activity_load_date_table_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/button" >
</TableLayout>
</RelativeLayout>
Java Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_load_date);
//Do something with my Buttons and TextViews(this works fine)
tblLayout = (TableLayout) findViewById(R.id.activity_load_date_table_layout);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.button_calc) {
for (int i = 0; i < listOfEntries.size(); i++) {
Entry temp = listOfEntries.get(i);
if (temp.getDate().getTime() >= startDate.getTime()
&& temp.getDate().getTime() <= endDate.getTime()) {
TableRow tr = new TableRow(this);
TextView comm = new TextView(this);
comm.setText(listOfEntries.get(i).getComment());
TextView val = new TextView(this);
val.setText(String.valueOf(listOfEntries.get(i).getValue()));
LayoutParams params = new LayoutParams(0,
LayoutParams.WRAP_CONTENT, 1f);
tr.setLayoutParams(params);
tr.addView(comm);
tr.addView(val);
tblLayout.addView(tr);
}
}
tblLayout.invalidate(); //Shouldn't this redraw the entire TableLayout and therefore adding my TableRows? This is not working.
}
}
Through various tests with TextViews and Toasts I have gathered that the tblLayout should be filled and the TableRows are added to the Layout, the only thing that is not working is the "repainting" of my Layout. How do I achieve that?
Edit:
Apparently the thing that made this not work was actually the LayoutParams given to the TableRow, once I commented those out I atleast got it printed to the screen. They are however not where I expect them to be.
I expected them to be below the buttons, instead they are in the top left corner on top of the buttons. This leads me to believe that the TableLayout is actually the same size as the RelativeLayout but is layered above the RelativeLayout. The error should therefor lie in my XML-File. What height do I need to give my TableLayout to make this work the way I expect?
Edit2:
I needed to add the android:layout_below attribute to my TableLayout, works as a charm now!
You need to call the method "requestLayout()"
Call this when something has changed which has invalidated the layout of this view. This will schedule a layout pass of the view tree.

Categories

Resources