Problem when moving TableRow within TableLayout - android

I am trying to dynmically move several rows around at once within a specific view based on user input.
The use-case is that the user picks an option and based on the option, certain rows are show/hidden and the rows need to be rearranged to make sense to the user.
The TableLayout is instantiated in XML, but the TableRow and it's layout(s) are instantiated in code. I have tried several different methods, with varying levels of success.
Code which works for hiding/disabling properly:
private void updateTimeRow(TargetType goalTarget)
{
TableRow timeRow = (TableRow)this.findViewById(timeId + 100);
EditText timeText = (EditText)this.findViewById(timeId);
if (goalTarget == TargetType.daysRowedWeek
|| goalTarget == TargetType.metersDay
|| goalTarget == TargetType.metersSeason
|| goalTarget == TargetType.metersWeek)
{
timeRow.setVisibility(View.GONE);
timeRow.setEnabled(false);
timeText.setEnabled(false);
}
else if (goalTarget == TargetType.splitForDistance
|| goalTarget == TargetType.unknown)
{
setTimeText(currentTarget.recalcTime().toString());
timeRow.setVisibility(View.VISIBLE);
timeRow.setEnabled(false);
timeText.setEnabled(false);
}
else
{
timeRow.setVisibility(View.VISIBLE);
timeRow.setEnabled(true);
timeText.setEnabled(true);
}
}
Based on questions answered here, I tried removing/re-adding rows, with this piece of code:
int rowNum = -1;
tableLayout.removeView(timeRow);
switch (goalTarget)
{
case unknown:
case timeForDistance:
rowNum = 2;
break;
case splitForDistance:
rowNum = 4;
break;
case splitForTime:
rowNum = 3;
break;
}
tableLayout.addView(timeRow, rowNum);
Two things break here:
The disable code fails (whether this code is run before of after the enable/disable code above
The rows in my layout get all screwed up.
So, how do I move the rows around dynamically, while properly hiding/showing/enabling/disabling the different rows?

After a lot of frustrating trial and error, I finally figured out the only way to do this with solid results:
I had to adjust the way my UI was updating, to a 3-step process:
- Update the values for the Inputs (enforces formatting, re-calcs, etc)
- Re-layout the rows
- Enable/disable the different inputs based on the selections
The nuts and bolts is that anytime the goalTarget changes I have to remove all of the TableRows from the TableLayout and add
them back in the correct order, with the appropriate row numbers as part of the addView() call.
This is definitely not the prettiest way I could see it being done, but apparently the TableLayout doesn't like you just trying
to move things around one at a time.

Related

Setting Text Based on values held in ArrayList

This is driving me a little mad since I know this should be very simple but I am not getting the desired affect.
I have the following arraylist
private List<String> tagStringArray = new ArrayList<>();
Then later I have a method that creates dynamic buttons, based on ID values pulled across from my Retrofit instance.
In my method, I have a count to help me set the title of the button but I also add the values of count to an ArrayList for use in another method.
I have taken a snip of relevant information from the method mentioned.
count = 1;
if (!questionNumber.equals("") && !questionNumber.equals(null)) {
for (final Object value : list) {
try {
/*Dynamically create new Button which includes the question number
*/
final AppCompatButton btn_question = new AppCompatButton(getActivity());
/*LayoutParams (int width, int height,float weight)
As LayoutParams is defaulted in px, I have called a method called dpToPX to make sure
the dynamically added EditText is the same size on all devices.
*/
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(280), dpToPx(45), 1);
btn_question.setBackgroundColor(Color.parseColor("#3B5998"));
btn_question.setTextColor(Color.WHITE);
btn_question.setText("Question "+count);
//set the Tag based on its position in the XML
tagStringArray.add(String.valueOf((count)));
count++;
If a user clicks on say Question 1 Button, I want my fragment to say Question 1, so to try and achieve that, I have tried doing the following:
String tags = String.valueOf(tagStringArray);
tags = tags.substring(1, tags.length() -1);
String[] currentTag = tags.split(",");
if (currentTag[0].contains("1")) {
tv_setQuestions_edit.setText("Question 1");
}else if(currentTag[1].contains("2")) {
tv_setQuestions_edit.setText("Question 2");
}
But this will always set the title to Question 1 and I am not sure what is going wrong.......
If I use the following toast Toast.makeText(getActivity(), Arrays.toString(currentTag), Toast.LENGTH_LONG).show(); it shows [1,2] so I know they are being added ok.
I did look into using tags by doing:
public static int KEY_COUNT=0; public static int KEY_VALUE=1;
btn_question.setTag(KEY_VALUE,value);
btn_question.setTag(KEY_COUNT,count);
But for some reason, when I add more than one tag (as I need a minimum of 2), my dynamic button is missing from the layout. But for some reason when only 1 tag - like this btn_question.setTag(value); is used, it shows up fine (I have a feeling its some issue with my fragment). Therefore I am trying to think of a workaround in the meantime.
Any help or guidance would be really appreciated.
It's because
currentTag[0].contains("1")
is always true. The first item of currentTag always contains "1".
Instead of doing this, why don't you just do String titleForFragment = myButton.getText() in the onClick method for the button? That way, you can set the same onClickListener on all the buttons, and it will reduce the amount of code you need to write.

Need to check array of imageviews for backgroundresource, clickable or imageresource (Android)

I'm creating a memory app (you know where you have to select 2 images and match them). I'm looking for a way to check when there are no images left so I can show a message.
I have this code to check if the images match. I'm working with 2 arrays, 1 holds the imageviews and their position in the grid (playfield) and one holds the reference for which image is on that imageview (cards).
private void checkCards() {
if (cards[value1] == cards[value2]) {
playfield[value1].setBackgroundResource(R.drawable.border_red);
playfield[value2].setBackgroundResource(R.drawable.border_red);
playfield[value1].setClickable(false);
playfield[value2].setClickable(false);
score++;
} else {
playfield[value1].setImageResource(R.drawable.back);
playfield[value2].setImageResource(R.drawable.back);
}
value1 = -1;
value2 = -1;
}
I need to check on one of these conditions:
There are no more imageviews without a red border
There are no more imageviews that are clickable
There are no more imageviews with the R.drawable.back imageresource
However I'm not sure on how to do this? Do any of you have an idea or even a better method?
Thanks in advance!
I would keep a counter of each one, I can think on more complicated solutions, but a pretty straightforward one will be to have a counter and increase that counter when you're assigning the clickables, the borders, etc... e.g:
private void checkCards() {
if (cards[value1] == cards[value2]) {
playfield[value1].setBackgroundResource(R.drawable.border_red);
playfield[value2].setBackgroundResource(R.drawable.border_red);
playfield[value1].setClickable(false);
playfield[value2].setClickable(false);
mCounterClickables--; // one less clickable
mRedDrawables++; // one more Red Drawable
mBlackDrawables--;
score++;
} else {
playfield[value1].setImageResource(R.drawable.back);
playfield[value2].setImageResource(R.drawable.back);
mBlackDrawables++; //
}
value1 = -1;
value2 = -1;
}
Then to validate that you're done:
public boolean imDone() {
return mBlackDrawables == 0 && mCounterClickables== 0
&& mRedDrawables == playfield.length;
}
Does it makes sense?
In this way you don't have to iterate over and over again, you will always have track of what the user has done.
Btw. The initial state of your variables should be something like this:
int mBlackDrawables = 0, mCounterClickables = playfield.length, mRedDrawables = 0;

Android: trying to show info based on what user profile has

I have a ListView and each row contains a different User object.
A User has these different fields:
List of things I like
List of things I hate
List of games I play
Description of myself
Now, when I populate the ListView, I want to show different things that each user has filled out. So for example, one row might show 'things I like' filled out, while another might show the 'description of myself'.
I don't want to adjacent rows to be showing the same type of row. All this code will be inserted into my BaseAdapter's getView methood.
What would be the best logic in terms of pseudocode to achieve this?
Thanks in advance!!
Updated: Solution
// Creates arraylist of elements that are complete in profile
List<String> profileElements = new ArrayList<String>();
if (user.getGameOwned() != null && user.getGameOwned().size() > 2) {
profileElements.add(KEY_GAMES_PLAYED);
}
if (user.getAboutMe() != null && !user.getAboutMe().isEmpty()) {
profileElements.add(KEY_ABOUT_ME);
}
if (user.getIAm() != null && user.getIAm().length > 2) {
profileElements.add(KEY_I_AM);
}
if (profileElements.size() > 0) {
String randomElement = profileElements.get(new Random().nextInt(profileElements.size() - 1));
if (randomElement.equals(KEY_GAMES_PLAYED)) {
// do whatever here
}
else if (randomElement.equals(KEY_ABOUT_ME)) {
// do whatever
}
}
You could try this approach, in your BaseAdapter put a verification if what list do you want to show.
For example:
int ctr = 1; // your counter - try to declare it on the global level
if(ctr<4){//your 4 types of list -
display(ctr); //print the current ctr
ctr++;
}else{
display(ctr);
ctr = 1; //make the value to 1 for the next batch of loop
}
code:
display(int index){
switch (index){
case 1:
//List of things I like
break;
case 2:
//List of things I hate
break;
case 3:
//List of games I play
break;
case 4:
//Description of myself
break;
default:
break;
}
}
You could also do random.nextInt(4) but it might have the same result each row.
I think what you're trying to do could be achieved using an ArrayAdapter and a custom row layout. It is well explained in this article. I'd recommend reading the whole thing but section 6 explains what you want to do.

Some Buttons are not clickable in Landscape mode

Problem is shown in picture , please go light on me , i'm not that experienced in android
but trying my best to do so...
Tried this in my Main.java:
package com.faisal.my_calculator;
import android.content.SharedPreferences;
// all remaining imports here.
public class Main extends ActionBarActivity implements View.OnClickListener {
// Buttons
Button btnOne, btnTwo, btnThree, btnFour, btnFive, btnSix, btnSeven,..., btnTan, btnExit;
case R.id.three:
if (y != 0) {
y = 0;
etDisp.setText("");
}
str = str.append(btnThree.getText());
etDisp.setText(str);
break;
.
.
.
.
case R.id.add:
if (TextUtils.isEmpty(etDisp.getText().toString())) {
return;
}
operator = "+";
if (x == 0) {
x = Double.parseDouble(etDisp.getText().toString());
etDisp.setText("");
} else if (y != 0) {
y = 0;
etDisp.setText("");
} else {
y = Double.parseDouble(etDisp.getText().toString());
etDisp.setText("");
x = x + y;
etDisp.setText(Double.toString(x));
}
break;
I tried for:
appconfigchanges solution = it is not even in my AndroidManifest.xml,
Now to the layout part : In emulator all things are fully spaced on screen but when i run app below(2nd screen comes as a result not like on Emulator which i worked hard and adjusted its full screen) more when i run it on my LG_OG in landscape only starting three rows come on the screen o.O ....? need help here as well ...!
If anything needed more i will post it....!(now almost all code i have posted) Again, be patient to your brother :)
Please don't handle any exception if it is not realy needed to handle. Remove your try catch while initializing the UI and setting clicklistener to buttons and check where your code is failing.
Second you don't need to handle UI changes on orientation change as it will be handled by android itself. This will be done like -on orientation change your activity will be recreated and your oncreate will be again called so set layout and initialize all the UI element in oncrete itself and remove unnecessary code from onConfigurationChanged method.
Always check for the null value in suspected code
if(btnDiv == null)
{
//condition
}
Add following code just before try
if(btnDiv == null)
{
throw new NullPointerException("Button are not initialized");
}
if exception is thrown then your buttons are not initialized.
Yes , what a pain it was , as debugger is the best friend of programmer , i debugged it and it directly took me to the buttons which i didn't make in Landscape but were present in portrait so Eclipse doesn't like this and was causing my different buttons to stay idle but after putting those buttons in landscape xml now everything works all awesome...!
Now just layout make-up is remained as two buttons are running here and there when i run it.! :p
Thanks guys for your time...!

Android application view containers are sticky

I need help, my layouts and containers are lingering on after I have used the code bellow to remove them.
For example I have page 1 that adds a small text that explains how to use the part of the program under scrutiny, and then the next page allows the user to add a name where there is a label with text Name: and a EditText to add the name in next to it.
Both the components 'stick' but the EditText is reproduced multiple times and I have no idea why! I would also like to stop the sticking.
By sticking I simply mean that the view does not leave view like it should(still visible).
Here is some code.
if(pageCount == lastPageCount--)
{
page2Layout.removeAllViews();
//page2Layout.setVisibility(View.GONE);
//Reset all text views.
helpText.setText("");
}
helpText.setLayoutParams(params);
helpText.setText("You cannot view this part sorry :S\n\n" +
"You cannot view this part sorry :S.\n" +
"You cannot view this part sorry :S");
page1Layout.addView(helpText);
page1Layout.setVisibility(View.VISIBLE);
}
else if(pageNumber == 2)
{
if(pageCount == lastPageCount++)
{
//page1Layout.setVisibility(View.GONE);
page1Layout.removeAllViews();
}
else if (pageCount == lastPageCount++)
{
page3Layout.setVisibility(View.GONE);
}
//Name Position + Containers etc
LinearLayout nameLayout = new LinearLayout(this);
nameLayout.setOrientation(LinearLayout.HORIZONTAL);
nameLayout.setLayoutParams(params);
TextView nameLabel = new TextView(this);
nameLabel.setLayoutParams(params);
nameLabel.setText("Name: ");
EditText nameTextField = new EditText(this);
nameTextField.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
//All to name layout.
nameLayout.addView(nameLabel);
nameLayout.addView(nameTextField);
page2Layout.addView(nameLayout);
page2Layout.setVisibility(View.VISIBLE);
}
Beware of the stupid mistakes coders can make when they stare at code too long.
if(pageCount == lastPageCount++)
For anyone who is also stuck similarly, lastPageCount++ will increment lastPageCount after the statement has run.
Therefore the wrong code is run.

Categories

Resources