Some alternative to hundreds of buttons - android

Im going to write some android app, which will basically consists of two activities. So first should have a lot of buttons (100+) and on click on any of them I will just get some special id and move to second activity. But is there any alternative to declare that hundreds of buttons and copy/paste one piece of code to every of them setting almost same onClickLister? Is there any special construction? Thanks
Edit: every of buttons are actually indexed from 1 to n. And on the click second activity will be launched and get that index to show it. I cant basically use any spinner or smth else, because there will be 3 rows of clickable things and each of them carring different images
Edit 2: so, to give you an idea, im going to do some table of buttons like in Angry Birds menu when you actually choosing the level you want to play. So, on click you will get id of button and start second activity

Call the method to add buttons
private void addButton(){
LinearLayout view = (LinearLayout) findViewById(R.id.linear_layout_id_here);
Button btn = null;
int w = 50;
int h = 25;
for(int i=1; i<100; i++) {
btn = new Button(this);
btn.setLayoutParams(new LayoutParams(w,h));
btn.setText("button " +i);
btn.setTag(""+i);
btn.setOnClickListener(onClickBtn);
view.addView(btn);
btn = null;
}
}
Call this method for handling onclick on button
private View.OnClickListener onClickBtn = new View.OnClickListener() {
public void onClick(View view) {
final int tag = Integer.parseInt(view.getTag().toString());
switch (tag) {
case 1:
// Do stuff
break;
case 2:
// Do stuff
break;
default:
break;
}
}
};

You should use a ListView.
ListViews are great for handling a lot of items at the same time. They are also natural for the user. Additionally, you use only one click listener - OnItemClickListener.
There's a useful example on how to work with ListViews in the Android Referenence.

You may add buttons in code, something like this:
#Override
public void onCreate(Bundle savedInstanceState) {
/*your code here*/
GroupView gw =findViewById(R.id.pnlButtonscontainer); //find the panel to add the buttons
for(int i=0; i<100; i++) {
Button b = new Button(this);
b.setLayoutParameters(new LayoutParameters(w,h));
b.settext = i+"";
b.setOnClickListener(new OnClickListener(){
});
}
}
I coded directly into browser, so some syntax error may appear in my code, but this is the point, a way, not the only one, to add 100 buttons.

Related

Android Development - Create a menu with 3 imageButtons

First of all english is not my first language but i will try my best.
Also... i am pretty sure my title choice was not the best so sorry for that.
Basically what i wanted to do is a menu with three ImageButtons but there is a tricky part (tricky for me at least) since every time i press one button that same button changes image (to a colored version instead of a grayed out image) and the other two change as well from colored version of their respective images to grayed out ones, actually only one of the other two will change since the purpose of this is to be able to activate only one at a time so it would not be possible to have the other two active at the same time.
Notice that this is not a menu on the top right corner but just a set of three ImageButtons on a activity or Fragment.
I already tried a lot of stuff to make that happen but so far no luck but i think i know why though i can't find a workaround for this since i am actually new in android dev.
what i tried was inside the setOnClickListener of any of those buttons such as:
eventsButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
ImageButton eventsButton = (ImageButton) view.findViewById(R.id.eventsButton);
eventsButton.setBackgroundResource(R.drawable.events_icon_active);
eventsButton.setClickable(false);
}
}
);
i tried to add the functions to change the other imageButtons as well like:
eventsButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
ImageButton eventsButton = (ImageButton) view.findViewById(R.id.eventsButton);
eventsButton.setBackgroundResource(R.drawable.events_icon_inactive);
eventsButton.setClickable(false);
ImageButton contactsButton = (ImageButton) view.findViewById(R.id.contactsButton);
contactsButton.setBackgroundResource(R.drawable.contacts_icon_inactive);
contactsButton.setClickable(true);
ImageButton interestsButton = (ImageButton) view.findViewById(R.id.interestsButton);
interestsButton.setBackgroundResource(R.drawable.interests_icon_inactive);
interestsButton.setClickable(true);
}
}
);
and i repeated that three time, always setting the other buttons clickable and setting their images to the inactive one (the grayed out one), also setting the button i click as no longer clickable.
But from what i gather i cant do any references to any other buttons inside the eventsButton.setOnClickListener like the buttons interestsButton or contactsButton, it will crash the app as soon as i touch any of those three buttons with the following error message:
Attempt to invoke virtual method 'void android.widget.ImageButton.setBackgroundResource(int)' on a null object reference
And it always point to the first line where i make a reference to another button other then the one used to start the setOnClickListener.
If you can just point me in the right direction i would be tremendously grateful.
All the best
You can declare your ImageViews as final outside the scope of the listener and when the onClickListener(View v) is called you can then just call setBackground because they are final and you can reference them from inside the listener.
Something like this:
final ImageView view1 = (ImageView) findViewById(R.id.view1id);
final ImageView view2 = (ImageView) findViewById(R.id.view2id);
view1.setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
// do whatever you want to the ImageViews
// view1.setBackground...
}
}
);
eventsButton.setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
ImageButton contactsButton = (ImageButton) view.findViewById(R.id.contactsButton);
contactsButton.setBackgroundResource(R.drawable.contacts_icon_inactive);
contactsButton.setClickable(true);
}
}
);
Your problem is in view.findViewById(R.id.contactsButton): view here is the button being clicked (the events one), and by calling view.findViewById(contactsButton) you are implicitly saying that the contact button is a child of view, which is not.
Just use findViewById() (from Activity), getActivity().findViewById() (from Fragments), or better container.findViewById() (if you have a reference to the layout containing the three buttons).
I'm not saying that yours is the most efficient way to deal with a menu, just pointing out your error.
You can first make things simple; I suggest:
you add 3 array (Arraylist might be better) fields in your activity class, one for the buttons, one for the active resources and one for the inactive resources
initialize those arrays in the onCreate method;
define a single onClickListener object and use it for all the buttons; Use a loop in the onClick method, see bellow.
In terms of code, it looks like this:
ImageButton[] buttons;
int[] activeResources;
int[] inactiveResources;
protected void onCreate2(Bundle savedInstanceState) {
View.OnClickListener onClickListener = new View.OnClickListener(){
public void onClick(View view) {
ImageButton clickedButton = (ImageButton) view;
for(int i = 0; i<buttons.length; i++){
ImageButton bt = buttons[i];
if(clickedButton==bt){
bt.setBackgroundResource(inactiveResources[i]);
bt.setClickable(false);
}else{
bt.setBackgroundResource(activeResources[i]);
bt.setClickable(true);
}
}
}
};
buttons = new ImageButton[3];
activeResources = new int[3];
inactiveResources = new int[3];
int idx = 0;
buttons[idx] = (ImageButton) findViewById(R.id.eventsButton);
inactiveResources[idx] = R.drawable.events_icon_inactive;
activeResources[idx] = R.drawable.events_icon_active;
idx = 1;
buttons[idx] = (ImageButton) findViewById(R.id.contactsButton);
inactiveResources[idx] = R.drawable.contacts_icon_inactive;
activeResources[idx] = R.drawable.contacts_icon_active;
idx = 3;
buttons[idx] = (ImageButton) findViewById(R.id.interestsButton);
inactiveResources[idx] = R.drawable.interests_icon_inactive;
activeResources[idx] = R.drawable.interests_icon_active;
for(int i =0; i<buttons.length; i++){
buttons[i].setBackgroundResource(activeResources[i]);
buttons[i].setOnClickListener(onClickListener);
}
}
Do not expect it to run right the way, I am giving only ideas, you have to look and see if it fit for you are looking for.

I need to get the id of the dynamically generating button

From this code it creates dynamic buttons accodring to a given value from another layout. I need to get the id of that and add another button (if dynamic button clicks then I need to add another button dynamically).
for (int i = 0; i < value1; i++) {
LinearLayout.LayoutParams paramsIButton = new LinearLayout.LayoutParams
((int) ViewGroup.LayoutParams.WRAP_CONTENT, (int) ViewGroup.LayoutParams.WRAP_CONTENT);
ibutton = new ImageButton(HomePage.this);
ibutton.setImageResource(R.drawable.add);
ibutton.setLayoutParams(paramsIButton);
paramsIButton.topMargin = -70;
paramsIButton.leftMargin = 370;
paramsIButton.bottomMargin = 30;
ibutton.setId(i);
ibutton.getPaddingBottom();
ibutton.setBackgroundColor(Color.WHITE);
ibutton.setAdjustViewBounds(true);
rR.addView(ibutton);
}
If I understood correctly from the additional information you provided on your comment, you need to know when a user clicked on a button. You could set an OnClickListener to your button.
// Somewhere in your activity . . .
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener(){
public void onClick(View v){
// The button is clicked! Do whatever you want.
}
});
}
// ...
// Rest of the code
// ...
Of course, you should replace R.id.button1 with your button's id.
Seems to me like you need to add an onClickListener for the dynamically added button.
Make your class implement OnClickListener and then add a listener for the dynamic button:
ibutton.setOnClickListener(this);
and add an onClick Listener within your class:
#Override
public void onClick(View v)
{
// do something with this ID
v.getId()
}
I don't know how you keep track of the bulbs and fans, I'd hope you don't do it via the UI elements alone. I'd probably do it a bit differently, creating a data structure to track the bulbs and fans and attach the specific bulb or fan object to the UI element as a tag.

disable button click for certain rows of buttons

I dynamically create Buttons by entering a word. If I write "met", it appears on the screen - one Button per letter. The same thing happens for the next word I enter, and it appears below the previous word --- as shown in the image above.
When I click on a Button it turns green. My question is, what is the best way to disable the clicking of a row of Buttons. Meaning, if the user clicks on the 'm' in "met" I want the user to only be able to click on the Buttons in "met" and to not be able to click on any of the Buttons in "had", "goes", or "ran"
Here is my code:
EDIT
int size = enter_txt.getText().toString().length();
for (int i=0; i<size; i++){
final Button dynamicButtons = new Button(view.getContext());
dynamicButtons.setLayoutParams(rlp);
dynamicButtons.getLayoutParams().width = 130;
dynamicButtons.getLayoutParams().height = 130;
dynamicButtons.setTag("0");
dynamicButtons.setId(1);
dynamicButtons.setText(edit_text_array[i]);
dynamicButtons.setBackgroundResource(R.drawable.button);
button_list.add(dynamicButtons);
linearLayout2.addView(dynamicButtons, rlp);
dynamicButtons.setOnClickListener(
new View.OnClickListener()
{
public void onClick(View view)
{
int i=0;
LinearLayout ll = (LinearLayout) dynamicButtons.getParent();
for(i=0; i<list_of_ll.size();i++){
if (ll == list_of_ll.get(i)){
list_of_ll.get(i).setId(i);
break;
}
}
if(list_of_ll.get(i).getId()==i)
ButtonOnClick(view);
}
});
}
linearLayout2.setId(0);
linearLayout2.setTag("0");
list_of_ll.add(linearLayout2);
EDIT
I created a List of the LinearLayouts for each row of Buttons. The Buttons turn green if the id of the LinearLayout is set to 1. When I click on a Button I want that LinearLayout to stay at 1 and have all other rows/LinearLayouts set to 0 so they become unclickable.
Currently, every Button I click turns green even if it's in a different row. Can someone please help me solve this issue?
Why you don't set Id in the for loop so that you are able to refer and set the onlicklistener to null like jpcrow already mentioned.
Set Id like:
YourCreatedBtn.setId(i+1);
//Id's setted programmatically don't.
have to be unique... But they should be
a positive number (referring to the
android documentation)
And in your on click method simply set onclicklistener for specified Id's to null. Just a hint, hope it helps
Update regarding Thread-openers Comment
I found two simple ways but i would prefer the one which is not commented out in the buttonIsClicked:
LinearLayout llrow;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
llrow = (LinearLayout) findViewById(R.id.test_layout);
//Adding 5 Buttons
for(int i = 0; i<5; i++) {
Button mybtn = new Button(this);
//set LayoutParams here
mybtn.setId(5);
mybtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
buttonIsClicked(v);
}
});
llrow.addView(mybtn);
}
}
private void buttonIsClicked(View v) {
/*ArrayList<View> myButtons = llrow.getTouchables();
for(int i = 0; i < llrow.getChildCount(); i++){
myButtons.get(i).setOnClickListener(null);
}*/
for(int i = 0; i<llrow.getChildCount(); i++){
llrow.getChildAt(i).setOnClickListener(null);
}
}
It's just a simplified Version of your code, but i'm sure you will get the Content..
What if found out is, that you don't have to set the ID in both cases.. You can easily get all the child over
YourRowLinearLayout.getChildAt(starting from 0 to n-1-Views you added)...
I didn't found a way around the for-loop... But this small-little loop will not break your neck regarding to Performance..
The outcommented-code is the second Approach, finding all the Child over getTouchables which logically leads to an ArrayList and that's exactly the reason why i don't like it. You have to initialize an arraylist...... However, this also won't break your neck regarding to Performance but a penny saved is a penny got! ;) Hope it helps and everything is clear. Both of them work! Please mark as accepted answere if it fits your Needs...
You have to distinguish between the two rows, either add them to different ViewGroups or you can use View.setTag(int key, Object tag)

Android calculator buttons

I am trying to make a calculator for Android. Here is the code for my buttons:
int[] button_ids = {
R.id.BtnNum0, R.id.BtnNum1, R.id.BtnNum2, R.id.BtnNum3, R.id.BtnNum4, R.id.BtnNum5, R.id.BtnNum6,
R.id.BtnNum7, R.id.BtnNum8, R.id.BtnNum9, R.id.BtnAdd, R.id.BtnSub, R.id.BtnDiv, R.id.BtnMult,
R.id.BtnClear, R.id.equals
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditTextValue = (EditText) findViewById(R.id.editText1);
TVValue = (TextView) findViewById(R.id.textView1);
buttons = new ArrayList<Button>();
for(int id : button_ids) {
Button button = (Button)findViewById(id);
button.setOnClickListener(this);
buttons.add(button);
}
}
How I can change this part to a block of code where I won't have to declare the IDs of the buttons? (e.g. R.id.BtnNum0)
int[] button_ids = {
R.id.BtnNum0, R.id.BtnNum1, R.id.BtnNum2, R.id.BtnNum3, R.id.BtnNum4, R.id.BtnNum5, R.id.BtnNum6,
R.id.BtnNum7, R.id.BtnNum8, R.id.BtnNum9, R.id.BtnAdd, R.id.BtnSub, R.id.BtnDiv, R.id.BtnMult,
R.id.BtnClear, R.id.equals
};
I have been searching for an answer, but I still can't find a solution.
What you can do, since this code seems to only set a single OnClickListener for all Buttons, is to do it in xml
For each Button set
android:onClick="functionName"
then in your code you can do away with all of the id's and your for loop. In Java just create a function like
public void functionName(View v)
{
switch (v.getId())
{
case R.id.buttonId:
// do work for this Button
break;
...
}
The way you are doing it is fine but this is how I prefer to handle this situation. You just have to give all of the Buttons the same function name in xml then use that name as your function name in Java. You also just have to be sure to declare the function with a void return type and make sure it takes a View as its one and only parameter as in my example.
The Button Docs also have an example of this
in your layout file add this to every button
<Button
...
android:onClick="btnClicked"
.../>
then in your code add this method and check for each button in this method
public void btnClicked(View v)
{
switch(v.getId())
{
case R.id.BtnNum0:
// your code
break;
....
}
}
That is likely the best solution unfortunately, unless you use some sort of annotation framework which still doesn't cut down much on the boilerplate.
edit:
You could try to get a pointer to whatever ViewGroup is holding the Button views and then getting all of its children, and then looping through them while casting them to Buttons as you go.
For example: If your Button objects in XML are housed in a LinearLayout, you could get the pointer to that and do something like this:
for(int i=0; i < ((ViewGroup)v).getChildCount(); ++i) {
Button nextChild = (Button) ((ViewGroup)v).getChildAt(i);
}
Of course, I recommend against this, but it is still a possibility.
As trevor-e suggested, you can give an annotation processor a try. Android Annotations can simplify your code to:
#Click
public void BtnNum0() {
// Button 0 clicked
}
#Click
public void BtnNum1() {
// Button 1 clicked
}
// etc.
If you go this route, please do try to use names following the Java convention as the button names correspond with function names.

Android: Knowing which button is pressed for buttons that are created programatically

I am trying to do this:
Programatically create 4 buttons on a layout. Then, create an onclick listener for each of the button. Then, based on which button is pressed, will do some logic.
I have created a LinearLayout in my XML file and called it "layout".
So, my codes go something like this:
layout = (LinearLayout)findViewById(R.id.layout);
//Create the array of buttons
Button [] subjectButtons_BT = new Button[4];
for(int i=0; i<4; i++){
subjectButtons_BT[i] = new Button(this);
// Add the button to the layout
layout.addView(subjectButtons_BT[i]);
subjectButtons_BT[i].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
// if it is the first button, do LOGIC1
// if it is the second button, do LOGIC2 etc
}
});
}
So far, I have managed to create the 4 buttons and I can click on the buttons.
However, I do not know how to the logic in the setOnClickListener part.
I wanted to know which button is pressed. So, I tried using v.getId() but it always returns a -1.
Can someone advise if this is the right way to go? And if so, how to do the logic?
Thanks.
You have two options for identify which dynamic button is clicked.
1) Set ID to the button and compare ID
2) Set Tag to the button if you have come more information about button
and want to access it
1) You can set id to the button and in onClick() method you can get id by button.getId() method and you can compare ids and perform action according to click.
2) If you set tag then you have to get tag by calling button.getTag() method and by this way you can pass object with the button
You can set the id of the buttons after you create them, and then check for that id within the OnClickListener
layout = (LinearLayout)findViewById(R.id.layout);
//Create the array of buttons
Button [] subjectButtons_BT = new Button[4];
for(int i=0; i<4; i++){
subjectButtons_BT[i] = new Button(this);
subjectButtons_BT[i].setId(i);
// Add the button to the layout
layout.addView(subjectButtons_BT[i]);
subjectButtons_BT[i].setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
int id = v.getId();
if (id == 0) {
} else if (id == 1) {
}
//etc.
}
});
}

Categories

Resources