I am working on an android server-client application. There is a connection between the android application and the server.
Based on the first message from the server, a number of buttons is created and displayed on the screen. This number usually is between 1 and 10.
I don't want to initialise 10 buttons in my activity, as maybe, in the future, the number of buttons will increase to 20.
This is the way I initialise buttons and show them on the screen:
actionButtons = server.getActionButtons();
TableLayout buttonLayout =
(TableLayout) rootView.findViewById(R.id.tblLayoutButtons);
for(int i=0; i< actionButtons.length; i++)
{
btnAction.setWidth(100);
btnAction.setHeight(50);
btnAction.setTag(actionButtons[i]);
btnAction.setText(actionButtons[i].getName());
btnAction.setOnClickListener(btnActionClick);
buttonLayout.addView(btnAction);
}
This all works well. But my problem is that the server sends statusupdates for the buttons, every 3 seconds. Each button stands for a light, that can be on or off. A button that is 'ON' should have another background than a button that is 'OFF'. The buttons should be updated every time an update from the server is received.
How could this be done?
I would make it like this:
public void createButtons() {
actionButtons = server.getActionButtons();
TableLayout buttonLayout = (TableLayout) rootView.findViewById(R.id.tblLayoutButtons);
for(int i=0; i< actionButtons.length; i++)
{
btnAction.setWidth(100);
btnAction.setHeight(50);
btnAction.setTag(actionButtons[i]);
btnAction.setText(actionButtons[i].getName());
btnAction.setOnClickListener(btnActionClick);
btnAction.setId(i);
buttonLayout.addView(btnAction);
}
}
public void updateButton() {
//Get the ID of the button to toggle from the server and get the related view
ToggleButton buttonToToggle = (ToggleButton) findViewById(Integer.parseInt(server.getMessage()));
if (buttonToToggle.isChecked()) {
buttonToToggle.setChecked(false);
buttonToToggle.setBackground(R.drawable.offImage)
}
else {
buttonToToggle.setChecked(true);
buttonToToggle.setBackground(R.drawable.onImage)
}
}
This has the advantage, that you just have to send the ID of the Button and it gets toggled.
Alternatively you could send the binary value off all buttons, so you have to send also just a few bytes... In this case, you can assign the buttons their value in a for loop, almost like you create them.
Hope I helped ;)
If you want to change status of an already created Button then while creating them at run time assign them unique Id's using setID(int) method from the View class.
So for your button1 you can,
button1.setId(100);
and when you want to change thngs you can fetch the ID for the button and change it appropriately.
if(toChangeButton.getID() == 100){
//Change button1
}
Hope this helps.
Try to use the listview to add the buttons.When you get the data from the server,just update the adapter of the listview.
Hope this helps.
Related
I need to add 5 Input fields (EditText) dynamically one by one on button click and want to take values from them and store them into database using Room Persistence with MVVM.
Here I'm adding the view dynamically
private void addEditTextView() {
View inputView = getLayoutInflater().inflate(R.layout.row_edit_text, null, false);
EditText val1 = inputView.findViewById(R.id.input_value_1);
binding.layoutList.addView(inputView);
}
Any suggestion would be very helpful.
Thank you in advance.
Add view based on child count
private void addEditTextView() {
if (binding.layoutList.getChildCount() <= 5) {
View inputView = getLayoutInflater().inflate(R.layout.row_edit_text, null, false);
EditText val1 = inputView.findViewById(R.id.input_value_1);
binding.layoutList.addView(inputView);
}
}
"When I clicked Add button it is adding input field one by one, this code is working but I just want to limit for 5 fields not more not less and take values from them."
If you want to add exactly 5 fields on button click I recommend designing a fragment with the 5 fields in place, then when the button is clicked, inflate the fragment into your parent view. Then code the fragment appropriately with the data you're working with.
Then if you wanted, you could deflate the fragment on button click to clear the view or add some other way to clear the fragment when you want. Much easier than what you're doing currently in my own opinion.
You might as well include a submit button in your fragment assuming this is some kind of form.
You can simply define an integer and increase it every time you add the EditText but you should check if your integer is less than 5 everytime the method is called.
Example
private void addEditTextView() {
int count = 0;
if (count < 5){
View inputView = getLayoutInflater().inflate(R.layout.row_edit_text, null, false);
EditText val1 = inputView.findViewById(R.id.input_value_1);
binding.layoutList.addView(inputView);
count++;
}
}
I have 10 toggleGroup Buttons with 4 radio buttons each. When you click one radio button within a toggle group, It will add the index value of the selected radio button to an Arraylist. THen I have a "save" button to save those values to a database.
public ArrayList<Integer> RightInt(){
for(ToggleGroup tg: toggleRDB()) {
tg.selectedToggleProperty().addListener((observable, oldValue, newValue) ->{
if(newValue != null) {
//adds the index of the selected RadioButton to selectedRDBIndex list
selectedRDBIndex.add(tg.getToggles().indexOf(newValue));
}
});
}
return selectedRDBIndex;
}
//selectedRDBIndex is an ArrayList<Integer> storage.
The code above returns a list of Integer with 10 values.
This code is the action performed by the save button.
for(int i = 0; i < 10; i++) {
//answerStore.storeRDB connects to my dataBase to save the values returned by the RightInt() function.
answerStore.storeRDB(i+1, TB, RightInt().get(i));
}
RightInt().clear();
The code above works well. It saves and updates values to my database.
Then I decided to use those values again here:
for(int i = 0; i<10 ; i++) {
toggleRDB().get(i).getToggles().get(answerStoration.retrieveDataRDBSet(i+1,TB)).setSelected(true);
}
//toggleRDB() returns a list of toggleGroups.
//answerStoration.retrieveDataRDBSet gets the radioButton integer data in the database that i used to setSelect an index of radioButton in each toggle group.
I used all these codes so that when the user selected a radioButton that progress will be saved. But after using the code above I can't update datas in my database. I hope you understood my situation and solve this problem. THanks in advance.
I got some hints on my problem. When I click a radio button
It adds another place on the arraylist that's why the values aren't changing. Now I need figure out where to place a set () method or how to replace those values. I would like to say that clearing the list is not an option.
This question is related to one I posted earlier. Views removed using removeView() are there when I next open the Activity (Android)
Background: When a user logs into my app they are taken from the login activity to the mainpage activity. The mainpage has a TableLayout that contains dynamically generated buttons. However if the user logs out and back in again, all of these buttons are repeated so I am trying to find out how best to remove these buttons after they are generated. In my previous post it was suggested I remove the buttons at the very start of the main page activity, before the new ones are drawn, so this is what I am trying to implement.
However when I call getChildCount() on this layout it does not always return the correct answer.
So far, here is the code that is run at the start of the main page activity:
TableLayout tableLayout = (TableLayout)findViewById(R.id.MainPageTableTitle);
//removeSectionButtons(tableLayout); this is where i am trying to remove the buttons
System.out.println("there are oncreate " + tableLayout.getChildCount());
drawButtons(tableLayout);
System.out.println("there are ondraw " + tableLayout.getChildCount());
The first print line returns 0 and the second print line always returns the correct answer (number of buttons drawn including all of the repeated ones). But I am not sure why getChildCount() returns the wrong answer the first time. If anyone can explain I would be incredibly grateful
My drawButtons() method is as follows (it draws two buttons per row):
public void drawButtons(TableLayout tableLayout){
//get the number of buttons
int noOfButtons = mySectionTableHandler.getSectionDetails().size();
//calculate the number of rows needed (there are 2 columns)
//set flag to say if buttons are odd as it affects how many are drawn
int noOfRows;
boolean evenNoOfButtons;
if(noOfButtons % 2 == 0){
//even no of buttons
noOfRows = noOfButtons/2;
evenNoOfButtons = true;
} else {
//odd no of buttons
noOfRows = (noOfButtons+1)/2;
evenNoOfButtons = false;
}
//counter to give each button a unique id
int counter = 1;
for(int i = 0; i<noOfRows;i++){
TableRow newRow = new TableRow(this);
Button a = new Button(MainPageActivity.this);
a.setId(counter);
sectionButtons.put(counter, a);
counter++;
newRow.addView(a);
//if there are even buttons OR if there are an odd no
//of buttons but this isn't the last row then add
//second button to row
if(evenNoOfButtons || (!evenNoOfButtons && (noOfRows-1!=i))){
Button b = new Button(MainPageActivity.this);
b.setId(counter);
sectionButtons.put(counter, b);
counter++;
newRow.addView(b);
}
tableLayout.addView(newRow);
}
}
This was my bad, turns out I was re-adding data to the sqlite database each time the user logged in without wiping previous details.
So my code was generating a button for every field in the database as it should have been.
I'm currently trying to create a cash register application. The user can press buttons to add products to their receipt.
The buttons should have a static text inside that tells users what the product is and how much it costs.
The button should also have a dynamic text called amount: 0x. That when pressed iterates + 1 so it shows amount: 1x.
How do I go about this? I'm pretty new to android so how can I have 1 button with one part static and 1 part dynamic text?
EDIT:
Thanks for all your answers so far but i'm not looking for a way to iterate the amount. By using setText I also overwrite the product and the cost of the product.
So I want a way to only update the amount when a button is pressed. Instead of using:
button.settext("Pepsi: 1,50" + amount + "x");
Is there a way or should I just use setText?
int counter = 0;
button.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
counter++;
button.setText("Amount" + counter + "x");
}
});
set a counter, listen for the click event for the button. Now inside click event increment the counter and set the new text to the button.
I am developing an app where the user has to match the image and corresponding name of it correctly.
My problem is when the user selects the image first and selects the wrong name it will display wrong answer and if he selects the answer it will be displayed correct answer.
The user should not have to re-select the image again
I have made the onClickListerner's null but it wont work some of my code is as follows,
txt_tag[0] = (TextView) findViewById(R.id.txt_tag1);
txt_tag[0].setOnClickListener(this);
txt_tag[0].setTypeface(tf);
txt_tag[1] = (TextView) findViewById(R.id.txt_tag2);
txt_tag[1].setOnClickListener(this);
txt_tag[1].setTypeface(tf);
txt_tag[2] = (TextView) findViewById(R.id.txt_tag3);
txt_tag[2].setOnClickListener(this);
txt_tag[2].setTypeface(tf);
txt_tag[3] = (TextView) findViewById(R.id.txt_tag4);
txt_tag[3].setOnClickListener(this);
txt_tag[3].setTypeface(tf);
img[0] = (ImageButton) findViewById(R.id.img1);
img[0].setOnClickListener(this);
img[1] = (ImageButton) findViewById(R.id.img2);
img[1].setOnClickListener(this);
img[2] = (ImageButton) findViewById(R.id.img3);
img[2].setOnClickListener(this);
img[3] = (ImageButton) findViewById(R.id.img4);
img[3].setOnClickListener(this);
btn_nxt = (Button) findViewById(R.id.btn_next);
btn_nxt.setOnClickListener(this);
and I have called an method inside that method where I have made all onClickListerner's null
txt_tag[0].setOnClickListener(null);
txt_tag[1].setOnClickListener(null);
txt_tag[2].setOnClickListener(null);
txt_tag[3].setOnClickListener(null);
img[0].setOnClickListener(null);
img[1].setOnClickListener(null);
img[2].setOnClickListener(null);
img[3].setOnClickListener(null);
Can anyone tell me where I am going wrong or any modifications I can do to it.
Thanks in advance
Try using
txt_tag[0].setClickable(false);
txt_tag[1].setClickable(false);
..
img[0].setClickable(false);
img[1].setClickable(false);
..
Your question is not that clear.. but if you want your image and text tag not clickable.. make them android:clickable="false" in xml or setClickable(false);
If I were you I would be checking that logic in a listener. So if the quiestion (if it's a quiz) is in the state "ANSWERED", don't react to event.
Your question is unclear, but I understand it as follows:
You have a bunch of ImageViews and a bunch of TextViews and a Mapping between them.
You want to be able to first select an ImageView, then a TextView. If they match, "correct answer" will be displayed somewhere, if not, "wrong answer" will be displayed
If you click on a TextView before an ImageView is selected, nothing happens
If you click on a Textview and another TextView is already selected, nothing happens
If that is correct, you can do this like this: You keep two variables
int selectedImage = -1;
int selectedText = -1;
In your OnClickListener you update their values like this:
if (source instanceof ImageViews) {
selectedImage = getArrayIndex(source); // I guess you already have a method to retrieve the index
selectedText = -1; // reset textSelection
} else {
if (selectedText < 0) {
selectedText = getArrayIndex(source);
}
}
updateAnswerTextView(); // here you check if the two selections (selectedText and selectedImage) match and display the corresponding string.
Instead, you could just iterate through the TextView array and call
setClickable(false);
on every element as soon as one is clicked. If a new image is selected, you will have to set them to clickable again.
EDIT: And I agree with Rob, you should not remove your Listeners to achieve this behaviour.
Here's my suggestion, if you want you code up specific behaviour you can use the onClickListener callback to achieve what you want.
In the listener, check the state of the image; if it is already selected and you want to ignore the event then you just exit from your callback.
I think setting the onClickListener to null is the wrong thing to do.