I have a TableLayout where I add dynamically TableRows. In each TableRow, I add a Button.
I just would like to add some space between my columns (which are my buttons) but I can't figure out how...
I've tried to change all the possible margins but it doesn't work :(
So maybe I made a mistake in my code where I inflate them from XML files:
private void createButtons(final CategoryBean parentCategory) {
final List<CategoryBean> categoryList = parentCategory.getCategoryList();
title.setText(parentCategory.getTitle());
// TODO à revoir
int i = 0;
TableRow tr = null;
Set<TableRow> trList = new LinkedHashSet<TableRow>();
for (final CategoryBean category : categoryList) {
TextView button = (TextView) inflater.inflate(R.layout.button_table_row_category, null);
button.setText(category.getTitle());
if (i % 2 == 0) {
tr = (TableRow) inflater.inflate(R.layout.table_row_category, null);
tr.addView(button);
} else {
tr.addView(button);
}
trList.add(tr);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
CategoryBean firstChild = category.getCategoryList() != null && !category.getCategoryList().isEmpty() ? category
.getCategoryList().get(0) : null;
if (firstChild != null && firstChild instanceof QuestionsBean) {
Intent intent = new Intent(CategoryActivity.this, QuestionsActivity.class);
intent.putExtra(MainActivity.CATEGORY, category);
startActivityForResult(intent, VisiteActivity.QUESTION_LIST_RETURN_CODE);
} else {
Intent intent = new Intent(CategoryActivity.this, CategoryActivity.class);
intent.putExtra(MainActivity.CATEGORY, category);
startActivityForResult(intent, VisiteActivity.CATEGORY_RETURN_CODE);
}
}
});
i++;
}
for (TableRow tableRow : trList) {
categoryLaout.addView(tableRow);
}
}
My button_table_row_category.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/buttonTableRowCategory"
style="#style/ButtonsTableRowCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/validate" />
My table_row_category.xml:
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tableRowCategory"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="100dp"
android:gravity="center"
android:padding="5dp" >
</TableRow>
Thank you for your help.
In the case of a TableLayout, Buttons themselves are the columns. That means you have to advise the Buttons to keep some space inbetween. You can do this by using layout parameters. They are much easier to set in XML, but it also works programmatically. It's important that you always use the LayoutParam class of the parent layout of the element where you apply it - in this case the parent is a TableRow:
// Within createButtons():
android.widget.TableRow.LayoutParams p = new android.widget.TableRow.LayoutParams();
p.rightMargin = DisplayHelper.dpToPixel(10, getContext()); // right-margin = 10dp
button.setLayoutParams(p);
// DisplayHelper:
private static Float scale;
public static int dpToPixel(int dp, Context context) {
if (scale == null)
scale = context.getResources().getDisplayMetrics().density;
return (int) ((float) dp * scale);
}
Most dimension attributes in Android take pixels if you set them programmatically - therefore you should use something like my dpToPixel() method. Please, don't EVER use pixel values in Android! You will regret it later on.
If you don't want the rightmost button to have this margin, just check with an IF and don't add the LayoutParam on it.
Solution in XML:
To avoid the LayoutInflater erasing your XML-defined attributes, do this while inflating (taken from Layout params of loaded view are ignored):
View view = inflater.inflate( R.layout.item /* resource id */,
MyView.this /* parent */,
false /*attachToRoot*/);
Alternative: Use a GridView like so: Android: Simple GridView that displays text in the grids
Add Padding Right for a component in the table row component
<TableRow
android:id="#+id/tableRow1">
<TextView
android:id="#+id/textView1"
android:paddingRight="20dp" />
</TableRow>
Try android:layout_marginRight="6dp" this worked for me.
Try Using the setColumnStretchable function of the TableLayout. Give it a columnn index and set its stretchable property to true.
Eg. If you have 3 columns.
TableLayout tblLayout;
tblLayout.setColumnStretchable(0, true);
tblLayout.setColumnStretchable(1, true);
tblLayout.setColumnStretchable(2, true);
The above will give you equal spacing between all 3 columns of the tableLayout.
Related
I am trying to make a dynamic Gridlayout, 3 by 3 in portrait, or 5 by 5 in landscape. The plan is to fill the grid with ImageViews for a Tic Tac Toe game. During the game, players can choose to change the orientation so the grid will also change dimension. So i made the ImageViews fill the grid dynamically:
ImageView xml:
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="90dp"
android:layout_height="90dp"
android:onClick="choiceClick"
android:layout_margin="10dp"
android:background="#color/cardview_dark_background">
</ImageView>
the grid in main xml:
<GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/tvGame"
android:layout_centerInParent="true"
android:columnCount="3"
android:rowCount="3"
android:id="#+id/grid">
</GridLayout>
the code where i try to fill the grid:
GridLayout ttt = (GridLayout)findViewById(R.id.grid);
ImageView iv = new ImageView(MainActivity.this);
if (intent.getStringExtra("orientation").equalsIgnoreCase("p")){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
if (ttt.getChildCount() > 0){
ttt.removeAllViews();
}
Log.i(TAG, "onCreate: " + iv.getParent()); // prints null
if(iv.getParent() != null){
((ViewGroup)iv.getParent()).removeView(iv);
}
ttt.setRowCount(5);
ttt.setColumnCount(3);
for (int i = 0; i < 10; i++){
iv.setTag(String.valueOf(i));
ttt.addView(iv); //error here, The specified child already has a parent. You must call removeView() on the child's parent first.
}
}
I tried finding solutions but i already have the removeAllViews that i keep seeing. this current code does not use the image xml, i was previously trying the inflate method.
You are in a FOR-LOOP and you try to add same "iv" multiple times to its "ttt" parent, so after one cycle "iv" already has a Parent....
Method rewritten (2nd time):
final GridLayout ttt = findViewById(R.id.grid);
final LayoutInflater cLayoutInflater = (LayoutInflater)ttt.getContext().getSystemService(LAYOUT_INFLATER_SERVICE);
final String cOrientation = intent.getStringExtra("orientation");
if (cOrientation.equalsIgnoreCase("p")) {
ImageView iv;
if (ttt.getChildCount() > 0) ttt.removeAllViews();
ttt.setRowCount(5);
ttt.setColumnCount(3);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
for (int i = 0; i < 10; i++) {
iv = (ImageView)cLayoutInflater.inflate(R.layout.ImageView);
//iv.setId(View.generateViewId()); //<-- I suggest to set ImageView ID here if you need it
iv.setTag(String.valueOf(i));
ttt.addView(iv);
}
}
In one of the activity of my app, I have a button where I want to display an image with each button click. For example:
By clicking the button of my activity, an image appears on screen as shown.
The second and following clicks on the button will results in the new image to append accordingly.
I would like to have some suggestion on how do I achieve this.
I made something similar to this but with TextView. Basically I did this:
XML:
For my case I made TableLayout Ex:
<TableLayout
android:id="#+id/existedTableLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/margin_standard">
<TableRow>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/number_text"
android:textAppearance="#android:style/TextAppearance.DeviceDefault.Large" />
</TableRow>
</TableLayout>
Activity
Note: Change it to ImageView for your case
/* //Get the TableLayout. Ex:
private TableLayout existedTableLayout = findViewById(R.id.existedTableLayout);
*/
/* Make onClickListerner to call below function */
private void addTableRowDynamically() {
//Make new Row
TableRow newRow= new TableRow(this);
TextView newNoTextView = new TextView(this);
//some TextView method, do your research about ImageView
newNoTextView.setLayoutParams(new TableRow.LayoutParams(0,ViewGroup.LayoutParams.WRAP_CONTENT, 1));
newNoTextView.setText("this is text");
newNoTextView.setTextAppearance(this, android.R.style.TextAppearance_DeviceDefault_Large);
// Add the TextView to the newRow
newRow.addView(newNoTextView);
// Add the newRow which contain the TextView to the TableLayout, below
existedTableLayout.addView(newRow, existedTableLayout.getChildCount());
}
Add a vertical LineaLayout and add views dynamically:
private void createViews() {
for (int i = 0; i < numberOfViews; i++) {
view = new ImageView(context);
int width = 300;
int height = 50;
view.setPadding(18, 10, 0, 0);
view.setLayoutParams(new LinearLayout.LayoutParams(width, height));
view.setId(i);
view.setGravity(Gravity.CENTER_VERTICAL);
view.setBackgroundColor(Color.parseColor("someColor"));
viewList.add(view);
}
}
Rect rectf = new Rect();
for (ImageView view : viewList) {
view.getGlobalVisibleRect(rectf);
coordinates.add(rectf.bottom);
}
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)
How to set gravity in programmingcally in a relativelayout. I have a XML layout with name chat_viewer_message.xml as below:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="4dip"
android:paddingBottom="4dip"
android:gravity="left"
android:background="#drawable/chat_bg_in">
<ImageView
android:id="#+id/avatar"
android:layout_width="32dip"
android:layout_height="32dip"
android:layout_marginLeft="4dip"
android:src="#drawable/avatar_1_1"
/>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/avatar"
android:paddingLeft="4dip"
/>
</RelativeLayout>
And code view in programming is as below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final int type = getItemViewType(position);
final View view;
if (convertView == null) {
final int resource = R.layout.chat_viewer_message;
view = activity.getLayoutInflater()
.inflate(resource, parent, false);
if (type == TYPE_MESSAGE)
((TextView) view.findViewById(R.id.text)).setTextAppearance(
activity, appearanceStyle);
} else
view = convertView;
final MessageItem messageItem = (MessageItem) getItem(position);
String name;
final String account = messageItem.getChat().getAccount();
final String user = messageItem.getChat().getUser();
final String resource = messageItem.getResource();
final boolean incoming = messageItem.isIncoming();
final String server_host = view.getResources().getString(
R.string.server_host);
if (isMUC) {
name = resource;
}
if (incoming) {
view.setBackgroundResource(R.drawable.chat_bg_in);
} else {
// I WANT TO GRAVITY TO RIGHT. HOW TO CODE? THANKS
view.setBackgroundResource(R.drawable.chat_bg_out);
}
return view;
}
See gravity at the relativelayout with id = background, the default gravity is LEFT, So I want to if !incoming the value gravity at relativelayout be RIGHT instead LEFT.
Thanks.
Cast view to container layout, in this case RelativeLayout, and use setGravity(int) on it:
if (incoming) {
view.setBackgroundResource(R.drawable.chat_bg_in);
} else {
// I WANT TO GRAVITY TO RIGHT. HOW TO CODE? THANKS
view.setBackgroundResource(R.drawable.chat_bg_out);
((RelativeLayout) view).setGravity(Gravity.RIGHT);
}
A word of caution (from the docs):
Note that since RelativeLayout considers the positioning of each child
relative to one another to be significant, setting gravity will affect
the positioning of all children as a single unit within the parent.
This happens after children have been relatively positioned.
There are two main ways to programmatically set the gravity in a RelativeLayout. You can either set the gravity for all child views (setGravity(int)) or set the gravity individually (params.addRule(int)). Note: These methods are not available for LinearLayouts.
To set the gravity for all children:
RelativeLayout relativeLayout = findViewById(R.id.myRelativeLaout);
relativeLayout.setGravity(Gravity.CENTER);
To set the gravity for a single view within a RelativeLayout:
MyView myView = findViewById(R.id.myView);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
myView.setLayoutParams(params);
Sources:
RelativeLayout.setGravity(int)
RelativeLayout.LayoutParams.addRule(int)
RelativeLayout.LayoutParams.removeRule(int)
It works perfectly for my case:
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.topMargin = 700;//in my case
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);//in my case
varButton.setLayoutParams(layoutParams);
You can use:
RelativeLayout.LayoutParams paramas = new RelativeLayout.LayoutParams();
params.gravity = Gravity.RIGHT;
view.setLayoutParams(params);
For more info about gravity parameters u can check this: Gravity
Use method, setGravity(int)
http://developer.android.com/reference/android/widget/RelativeLayout.html#setGravity(int)
It's better way to set child's gravity by using RelativeLayout.LayoutParams.
See this.
How to programmatically set the layout_align_parent_right attribute of a Button in Relative Layout?
Building up chat layout and manipulating it programmatically &
sDirectionHasmap contains direction of each message.
if (sDirectionHashMap.get(idsList.get(position)).equals("incoming")) {
holder.messageLayout.setGravity(Gravity.LEFT);
} else {
holder.messageLayout.setGravity(Gravity.RIGHT);
}
I want to remove the extra padding that appears in a grid view. I have images of the size 128*128 which will be occupying cells in the grid. But somehow there is an extra space that gets added to the contents of the grid.
After some research, I was able to determine that I have to override the listSelector property of the grid view. Now here's my question - I know I have to specify something like an xml drawable here, but what to specify in that?? I tried using a shape drawable with padding and stroke set to 0dp to no avail.
The question is asked and answered here, but they haven't given what the drawable must contain.
Can some one help me with this. Thanks!
EDIT: Ok - here's a copy of the UI that I have. And the XML layout for the same is as follows:
<GridView android:id="#+id/GV_A2ZMenu" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:numColumns="4"
android:layout_gravity="top" android:stretchMode="columnWidth"
android:gravity="center" android:listSelector="#null" />
And I am using a BaseAdapter class to populate the gridView. Here's its code:
public class AtoZMenu extends BaseAdapter {
private static Context AppC;
private Integer[] MenuImg = { R.drawable.alphabet_a, R.drawable.alphabet_b,
R.drawable.alphabet_c, R.drawable.alphabet_d,
R.drawable.alphabet_e, R.drawable.alphabet_f,
R.drawable.alphabet_g, R.drawable.alphabet_h,
R.drawable.alphabet_i, R.drawable.alphabet_j,
R.drawable.alphabet_k, R.drawable.alphabet_l,
R.drawable.alphabet_m, R.drawable.alphabet_n,
R.drawable.alphabet_o, R.drawable.alphabet_p,
R.drawable.alphabet_q, R.drawable.alphabet_r,
R.drawable.alphabet_s, R.drawable.alphabet_t,
R.drawable.alphabet_u, R.drawable.alphabet_v,
R.drawable.alphabet_w, R.drawable.alphabet_x,
R.drawable.alphabet_y, R.drawable.alphabet_z };
public AtoZMenu(Context C) {
AppC = C;
}
public int getCount() {
return MenuImg.length;
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView IV;
float density = AppC.getResources().getDisplayMetrics().density;
if (convertView == null) {
IV = new ImageView(AppC);
IV.setMaxHeight((int) (1));
} else {
IV = (ImageView) convertView;
}
IV.setImageResource(MenuImg[position]);
return IV;
}
}
Can you spot the mistake?
Note: In the end I ended up implementing a similar screen in a table layout which renders much better grids.
Yep, I've had the same problem. You want to set the listSelector to #null:
<!-- Setting the listSelector to null removes the 5px border -->
<GridView
android:id="#+id/view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:listSelector="#null" />
Also, try the following:
myGridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
I see you can do this in the XML, but I didn't when I had this same problem; not sure why.
I also hard-coded the key height:
float density = getContext().getResources().getDisplayMetrics().density;
mKeyHeight = (int) (56 * density);
....
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageButton b = (ImageButton) convertView;
if (b == null) {
b = new ImageButton(getContext());
b.setMinimumHeight(mKeyHeight);
b.setBackgroundResource(R.drawable.btn_keyboard_key);
b.setOnClickListener(this);
}
}
Sorry about not giving a precise answer, so let me know if you still need help after that.
The correct answer is to set android:listSelector to #android:color/transparent, as user mvds said here.
I used a variation of Shawn's solution.. it looks nice on the Emulator.
1) Decide on the # of columns, I chose 4
2) Set the Column Width
float xdpi = this.getResources().getDisplayMetrics().xdpi;
int mKeyHeight = (int) ( xdpi/4 );
GridView gridView = (GridView) findViewById(R.id.gridview);
gridView.setColumnWidth( mKeyHeight );// same Height & Width
3) Setup the image in your adapter's getView method
imageView = new ImageView( mContext );
// (xdpi-4) is for internal padding
imageView.setLayoutParams(new GridView.LayoutParams( (int) (xdpi-4)/2, (int) (xdpi-4)/2));
imageView.setScaleType( ImageView.ScaleType.CENTER_CROP );
imageView.setPadding(1, 1, 1, 1);
4) Layout
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="4"
android:verticalSpacing="0dp"
android:horizontalSpacing="0dp"
android:gravity="center"
android:listSelector="#null"
/>
<!--
android:columnWidth="90dp" Specified in code
android:stretchMode="columnWidth" no noticable change
-->
That's it.
Even I had the same problem.
Try this:
image.setLayoutParams(new GridView.LayoutParams(imageWidth , imageHeight));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);.
Add padding accordingly for the images.It worked for me.
I had a similar problem, though in my case there was a quite large padding area at the bottom of my GridView (it was filled with the background color).
I haven't seen the solution to my issue here, so I'll post it here in case it's helpful.
Besides setting:
android:listSelector="#null"
in my GridView, I also had to set:
android:fadingEdgeLength="0px"
Or, in Java:
GridView.setFadingEdgeLength(0);
Try to give padding in pixels like this
android:paddingLeft="5px"