Simple card game setup creating rows and columns number of cards:
TableLayout tableCards = new TableLayout(this);
RelativeLayout.LayoutParams relLayParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
relLayParams.addRule(RelativeLayout.CENTER_IN_PARENT);
tableCards.setLayoutParams(relLayParams);
int i = 0;
StringBuilder sbCardsDebug = new StringBuilder('\n');
for (int r = 0; r < rows; r++) {
// create a new row
TableRow tr = new TableRow(this);
tr.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
for (int c = 0; c < columns; c++) {
ImageView card = new ImageView(this);
card.setTag("" + i);
card.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT));
card.setImageDrawable(bitmapCardBackScaled);
tr.addView(card);
card.setOnClickListener(cardClickListener);
i++;
}
// add the row:
tableCards.addView(tr);
}
relativeLayoutCardsHolder.addView(tableCards);
Somewhere in the listener I have a code part like this:
imageView.setVisibility(View.INVISIBLE);
Where the imageView is a card ( I have breakpoint set up also log and it shows the correct card.
The problem: it doesn't become invisible.
I am thinking maybe I am not in a good Thread or should I need something to do it after setting the invisible?
I have tried with :
imageView.post(new Runnable() {
public void run() {
imageView.setVisibility(View.INVISIBLE);
}
});
and
TableLayout parent = (TableLayout) imageView.getParent().getParent();
parent.invalidate();
parent.requestLayout();
and no success. Pls make any suggestion, I am out of ideas, thanks.
Edit1:
As suggestion I have tried with postDelayed too:
imageView.postDelayed(new Runnable() {
public void run() {
imageView.setVisibility(View.INVISIBLE);
}
}, 600);
Listener body is from line 353 to 424 calling several classes with animations, passing references and it will reveal my dirty work, also will show the business logic too (NDA agrement), which part are you interested? - min 1000 lines are executed.
If it's a correct ImageView, its must work.
imageView.setAlpha(0);
Hope it's help.
Related
I have about 100 views (Buttons,Textviews and ImageButton) in my activity that i create in a for loop. My app runs slow on older versions of android ( 5 and below) and sometimes it does not even load the views.
My question is, what is the proper way of handling such views and loading them without putting too much load on the main thread?
I couldn't use a separate thread since i cant reference UI elements from any other thread than the main one.
Thanks.
for (int i = 0; i < arr.size(); i++) {
String name = arr.get(i).getName();
final int songPath = arr.get(i).getSongPath();
int iconPath = arr.get(i).getIconPath();
RelativeLayout relativeLayout = new RelativeLayout(this);
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
relativeLayout.setLayoutParams(rlp);
buttons[i] = new ImageButton(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 350);
params.setMargins(0, 0, 0, 8);
buttons[i].setLayoutParams(params);
buttons[i].setBackgroundResource(iconPath);
buttons[i].setTag(name + "button");
buttons[i].setId(id++);
TextView emoteName = new TextView(this);
RelativeLayout.LayoutParams textParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
textParams.addRule(RelativeLayout.BELOW, buttons[i].getId());
textParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
textParams.setMargins(20,10,0,0);
emoteName.setText(name.toUpperCase());
emoteName.setId(id++);
emoteName.setTextSize(20f);
emoteName.setLayoutParams(textParams);
Button threedots = new Button(this);
RelativeLayout.LayoutParams threedotsParams = new RelativeLayout.LayoutParams(50, RelativeLayout.LayoutParams.WRAP_CONTENT);
threedotsParams.addRule(RelativeLayout.BELOW, buttons[i].getId());
threedotsParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
threedotsParams.addRule(RelativeLayout.ALIGN_RIGHT,buttons[i].getId());
threedotsParams.setMargins(0,0,0,0);
threedots.setText(getString(R.string.vertical_ellipsis));
threedots.setTextSize(25f);
threedots.setBackgroundColor(Color.TRANSPARENT);
threedots.setLayoutParams(threedotsParams);
final int counterForOnClick = i;
threedots.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ShowDialog(arr.get(counterForOnClick));
}
});
relativeLayout.addView(buttons[i]);
relativeLayout.addView(emoteName);
relativeLayout.addView(threedots);
if (i % 2 == 0) {
leftLayout.addView(relativeLayout);
} else {
rightLayout.addView(relativeLayout);
}
final int index = i;
buttons[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playEmoteSound(songPath);
}
});
}
As you said - adding all those views is not the best idea.
From your code, I can see that we are talking about the same views with different data.
You will want to use RecyclerView in order to create a list of the same view.
From the documentation:
If your app needs to display a scrolling list of elements based on large data sets (or data that frequently changes), you should use RecyclerView as described on this page.
This will be a little hard to explain, but I'll do my best!
I've got a spinner with numbers from 1 to 50. When I tap on a number, the script I wrote creates a number of TableViews like the number I tapped (eg: tap 3 --> 3 TableViews).
The problem occurs when I tap to another number: I want to have my previous view replaced with the new number, instead of being added at the end of it!
Just to explain better: I tap 3 and it creates 3 views; then I tap 4: I want to have 4 views now, but it gives me 7 because it does 3+4. If i tap 50 now, I'll have 57 views instead of 50 and so on...really dunno how to make this work.
Thanks for the help!
This is the full code but I'm sure you're not interested in what I do inside my OnItemSelectedListener...anyway I'll post it here, just in case you need it!
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
for (int j = 1+pokeIds.size(); j <= (int)spinner.getSelectedItem()+pokeIds.size(); j++) {
//get a reference for the TableLayout
TableLayout table = (TableLayout)findViewById(R.id.internalcopies);
//create a new TableLayout
TableLayout internaltable = new TableLayout(getApplicationContext());
// create a new TableRow
TableRow row = new TableRow(getApplicationContext());
TableRow attackRow = new TableRow(getApplicationContext());
TableRow ultiRow = new TableRow(getApplicationContext());
ImageView iv = new ImageView(getApplicationContext());
iv.setImageResource(imageAdapter.mThumbIds[pokeID-1]);
TableRow.LayoutParams params = new TableRow.LayoutParams(200,200);
iv.setLayoutParams(params);
attackSpinner = new Spinner(getApplicationContext());
ultiSpinner = new Spinner(getApplicationContext());
attackSpinner.setBackgroundColor(getResources().getColor(R.color.erba));
ultiSpinner.setBackgroundColor(getResources().getColor(R.color.erba));
params = new TableRow.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
attackSpinner.setLayoutParams(params);
ultiSpinner.setLayoutParams(params);
attackSpinner.setId(j);
ultiSpinner.setId(j*10);
editText = new EditText(getApplicationContext());
if (dpi == 480) {
editText.setWidth(250);
editText.setTextSize(13);
}
else if (dpi == 420)
editText.setWidth(300);
editText.setHint("(Nome)");
editText.setHintTextColor(getResources().getColor(R.color.acciaio));
editText.setTextColor(getResources().getColor(android.R.color.black));
editText.setId(j*11);
List<String> attacks = pokemonHelper.getMoves(pokeID, "HasAttack");
ArrayAdapter<String>attacksAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, attacks);
attacksAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
attackSpinner.setAdapter(attacksAdapter);
List<String> ultis = pokemonHelper.getMoves(pokeID, "HasUlti");
ArrayAdapter<String>ultiAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, ultis);
attacksAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
ultiSpinner.setAdapter(ultiAdapter);
// add the TextView to the new TableRow
params.gravity = Gravity.CENTER_VERTICAL;
params.setMargins(0,10,0,0);
row.addView(iv);
editText.setLayoutParams(params);
row.addView(editText);
attackRow.addView(attackSpinner);
ultiRow.addView(ultiSpinner);
internaltable.addView(attackRow);
internaltable.addView(ultiRow);
internaltable.setLayoutParams(params);
row.addView(internaltable);
// add the TableRow to the TableLayout
table.addView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT, TableLayout.LayoutParams.WRAP_CONTENT));
}
}
#Override
public void onNothingSelected(AdapterView<?> parent){}
});
You should remove all the children of the table before you start adding new ones:
//get a reference for the TableLayout
TableLayout table = (TableLayout)findViewById(R.id.internalcopies);
table.removeAllViews();
for (int j = 1+pokeIds.size(); j < (int)spinner.getSelectedItem()+pokeIds.size(); j++) {
...
}
I am creating a Android app. This Android App will have objects that are dynamic. These objects are Places with a Address or Lat/Long, and distance from current location, and a ETA. What I would like to do is add with objects on a TableLayout with borders, but I need to be able to dynamically add rows as the number of places increase.
I understand somewhat how to do this for a fixed hardcoded number of items on the xml, but what would be the best way when the number of objects is coming from the Activity.java file?
Below is a screenshot of the TableLayout I would like:
So the object would be a place with a address, distance and direction.
but I need to be able to dynamically add rows as the number of places increase.
This isn't difficult, when you have a new object append a TableRow with the data to the TableLayout.
I understand somewhat how to do this for a fixed hardcoded number of items on the xml, but what would be the best way when the number of objects is coming from the Activity.java file?
I don't think there is a best way (or what you consider best way). You either:
Insert fake views to act as dividers. This would be easier to implement visually but it will also increase the memory consumption of your app, with bad consequences if the number of rows is big. (1)
Or use drawables for the backgrounds to simulate the borders (like nine-patch images). This would be simpler then inserting additional views but you need a bit more talent to make it look well. (2)
Some examples for your image:
(1)
private static final int DIVIDER_SIZE = 2;
// rowsCount the number of rows to add to the TableLayout
private void buildOldSchool(TableLayout table, int rowsCount) {
View divider;
for (int i = 0; i < rowsCount; i++) {
TableRow row = new TableRow(this);
for (int j = 0; j < 7; j++) {
if (j % 2 == 0) {
divider = new View(this);
divider.setLayoutParams(new TableLayout.LayoutParams(
DIVIDER_SIZE, TableLayout.LayoutParams.MATCH_PARENT));
divider.setBackgroundColor(Color.GREEN);
row.addView(divider, new TableRow.LayoutParams(
DIVIDER_SIZE, TableRow.LayoutParams.MATCH_PARENT));
continue;
}
TextView tv = new TextView(this);
tv.setText("DX"); // dummy data
row.addView(tv, new TableRow.LayoutParams(
TableRow.LayoutParams.MATCH_PARENT,
TableRow.LayoutParams.WRAP_CONTENT));
}
divider = new View(this);
divider.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT, DIVIDER_SIZE));
divider.setBackgroundColor(Color.GREEN);
if (i == 0) {
table.addView(divider);
divider = new View(this);
divider.setLayoutParams(new TableLayout.LayoutParams(
TableLayout.LayoutParams.MATCH_PARENT, DIVIDER_SIZE));
divider.setBackgroundColor(Color.GREEN);
}
table.addView(row);
table.addView(divider);
}
}
(2) or with images:
private void buildWithDrawables(TableLayout table, int rowsCount) {
for (int i = 0; i < rowsCount; i++) {
TableRow row = new TableRow(this);
row.setBackgroundResource(i == 0 ? R.drawable.firstrow
: R.drawable.normalrow);
for (int j = 0; j < 3; j++) {
TextView tv = new TextView(this);
tv.setBackgroundResource(j == 2 ? R.drawable.extra
: R.drawable.cell);
tv.setText("DX");
row.addView(tv, new TableRow.LayoutParams(
TableRow.LayoutParams.MATCH_PARENT,
TableRow.LayoutParams.WRAP_CONTENT));
}
table.addView(row);
}
}
Where the images are:
R.drawable.cell:
R.drawable.extra (a visually transparent drawable which replicates the nine-patch above):
R.drawable.normalrow:
R.drawable.firstrow:
Ignore my design skills.
If your foresee a large number of rows I would advise you to use a ListView, which you could pretty easy make it to look like a table with borders.
Couldn't figure out the vertical line, but something you can build upon
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ScrollView sv = new ScrollView(this);
TableLayout ll=new TableLayout(this);
HorizontalScrollView hsv = new HorizontalScrollView(this);
for(int i=1;i<5;i++) {
TableRow tbrow=new TableRow(this);
for(int j=1;j<=3;j++) {
TextView tv1=new TextView(this);
tv1.setText("Element :"+ i + "" + j);
tbrow.addView(tv1);
}
ll.addView(tbrow);
View v = new View(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 5);
v.setLayoutParams(params);
v.setBackgroundColor(getResources().getColor(android.R.color.white));
ll.addView(v);
}
hsv.addView(ll);
sv.addView(hsv);
setContentView(sv);
}
The idea is to create TextViews for programs in nice little 200x200 squares in the shape of your favourite tetris squares. These views then move on to their own course relevant to themselves.
Problem im facing is this:
The first two views have this step difference from the top that comes from nowhere. Need to align them side by side instead.
I've checked their margins when debugging, and it was the same, as well as the layout they are in and well, the code below.
Relevant code below:
for (int i = 0; i < 2; i++) {
TableRow tr = new TableRow(this);
tr.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
// within each tablerow, we then create the tablecolumns
// assuming we want two columns only. Change 2 otherwise.
for (int j = 0; j < 2; j++) {
try {
TextView nyan = new TextView(this);
nyan.setText(pail.get(count).getProgramName());
nyan.setClickable(true);
nyan.setLayoutParams(new LayoutParams(200, 200));
nyan.setGravity(Gravity.CENTER);
//nyan.setPadding(10, 50, 10, 50);
nyan.setBackgroundColor(R.drawable.programlistback);
nyan.setSingleLine(false);
nyan.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = new Intent(v.getContext(),
CourseList.class);
i.putExtra("selectedProgram", pail.get(count)
.getProgramID());
startActivity(i);
}
});
tr.addView(nyan);
// when done with textview creation, update tick for nyan
count++;
} catch (IndexOutOfBoundsException e) {
Log.i("expect", "tableOrigin - hit " + count + "th index");
}
}
tabLayout.addView(tr, new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
}
Im implementing tablelayout dynamically code below.
private void showCowsTblField() {
for (int row = 0; row < numberOfRowsInField - 1; row++) {
TableRow tableRow = new TableRow(this);
tableRow.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
for (int column = 0; column < numberOfColumnsInField - 1; column++) {
LayoutParams layoutParams = new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
if (column == 0) {
textSno[row][column].setLayoutParams(layoutParams);
layoutParams.setMargins(0, 0, 0, 0);
tableRow.addView(textSno[row][column]);
} else {
blocks[row][column].setLayoutParams(layoutParams);
layoutParams.setMargins(1, 1, 1, 1);
tableRow.addView(blocks[row][column]);
}
tableRow.setBackgroundResource(R.drawable.bar_1);
}
tblCows.addView(tableRow, new TableLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
}
here block is a class extends Button class,
in this class iam setting background image as
this.setBackgroundResource(R.drawable.edit_button);
Here problem is the button background image size(height) is changing to fit to tablerow height. which is not looking good.
How i can set button background image to actual size (wrapcontent) in table row.
Please let me know....
Thanks.........
See if that helps - http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
You can set it only if you use http://developer.android.com/reference/android/widget/ImageButton.html
Your code must look something like this:
class MyButton extends ImageButton{...}
this.setScaleType(scaleType);
I tried the following code in my class; which extends button class
this.setMaxHeight(26);
this.setMaxWidth(54);
solved issue.:)