Reduce code for Button onClick events - android

My question has three parts.
My Layout consists of 26 Buttons: ButtonA, ButtonB, ButtonC...ButtonZ
The buttons are arranged in order on the screen. When the button is clicked I want to capture the click event and filter a SQLiteDB of words by the first letter that was clicked.
How do I write the minimum amount of code that will capture the click, identify the button's corresponding letter, and return the letters that begin with the selected letter from the SQLite Database?
Below is my code that has not been optimized for code brevity.
//Create your buttons and set their onClickListener to "this"
Button b1 = (Button) findViewById(R.id.Button04);
b1.setOnClickListener(this);
Button b2 = (Button) findViewById(R.id.Button03);
b2.setOnClickListener(this);
//implement the onClick method here
public void onClick(View v) {
// Perform action on click
switch(v.getId()) {
case R.id.Button04:
//Toast.makeText(this,"test a",Toast.LENGTH_LONG).show();
// Do the SqlSelect and Listview statement for words that begin with "A" or "a" here.
break;
case R.id.Button03:
//Toast.makeText(this,"test b",Toast.LENGTH_LONG).show();
// Do the SqlSelect and Listview statement for words that begin with "A" or "a" here.
break;
}
}

If you have lots of characters and a button for each character, I would probably extend the "BaseAdapter" class and make a ButtonAdapter holding the alphabet as a character array, instead of actually making 28:ish buttons... ...if I understood the problem correctly?
The getView could look something like this:
public View getView(int position, View convertView, ViewGroup parent) {
Button button;
if (convertView == null) {
button = new Button(mContext);
button.setTag(alphabet[position]);
button.setOnClickListener(clickListener);
} else {
button = (Button) convertView;
}
button.setText(alphabet[position]);
return button;
}

If your layout is defined in XML, you may want to use the android:onClick parameter for your buttons. This way you can save the findViewById() and setOnClickListener() calls.

As alextsc says, you can bind the click listeners from XML if you wish you reduce code in your Activity. However, I think it might be nicer to define the buttons in code inside a loop given their nature. Just make a simple container in your layout (e.g. a LinearLayout) and add to buttons to that. We can exploit the fact that you can loop over characters (treating them like integers) like so:
for (char letter = 'a'; letter <= 'z'; letter++) {
Button button = new Button(this);
button.setText(String.valueOf(letter));
button.setOnClickListener(this);
container.addView(button);
}
As for your actual click listener, you don't really need to switch on their IDs to do what you want. You know that the data for the button is just their text value. Just extract that and use it in a uniform way:
public void onClick(View v) {
Button button = (Button) v;
String letter = button.getText().toString();
// filter using letter
}

Related

100 Buttons and only 1 Active

I have one activity and here i have 100 buttons, i want that when i press Button 1 then press another Button the Button 1 should get unpressed.
i know i can make this with
if(Button1.isPressed()) {
Button2.setPressed(false);
Button3.setPressed(false);
Button4.setPressed(false);
Button5.setPressed(false);
Button6.setPressed(false);
Button7.setPressed(false);
Button8.setPressed(false);
......................... }
else { do nothing }
.... BUT!
it's too much code
Coders will kill me or will just laugh on me.
any ideas?
maybe there is a way to unpress the all buttons from the activity?
Not the prettiest solution ever, but you could make an OnClickListener like this:
View.OnClickListener listener = new View.OnClickListener() {
public void onClick(View v) {
ViewGroup parent = (ViewGroup) v.getParent();
for (int i = 0; i < parent.getChildCount(); i++) {
View current = parent.getChildAt(i);
if (current != v && current instanceof Button) {
((Button) current).setPressed(false);
}
}
((Button) v).setPressed(true);
}
}
and attach it to all of your buttons.
Then, whenever a button is clicked, it will iterate over all views that are in the same layout (or actually, view group) as the clicked button, and, for any of those views that are buttons except for the clicked button, it will call setPressed(false).
Note that this only works out of the box if all the buttons are in the same layout. If they are in nested layouts, you will have to adapt it a little.
Off topic: What do you need 100 buttons for? That's a lot of buttons. You may want to redesign your user interface
Ok so instead of looping through all the buttons on over and over again when one button is pressed, you can just store a variable which stores the button number of the button that was last pressed. Now, when the second button is pressed, disable the button that was pressed earlier, you get its index from the saved variable, enable the button that was pressed and store its index in the variable.
Heres an example pseudo code to give you and idea:
int buttonLastPressed = 0;
void onButtonClick(Button buttonPressed){
if(buttonLastPressed != 0){
disableButton(buttonLastPressed);
enableButton(buttonPressed);
buttonLastPressed = buttonPressed.getIndex()
}
}
Saves you from looping through each and every button to disable it.
Define id of button 1 to 100
When press button occurs save it's id in some member variable like previous_pressed
Before updating a previous_pressed value find and unpress previous pressed button like this
Button previous_pressed_button = (Button) findViewById(previous_pressed);
Now you have the previous pressed button, So upress it or whatever.

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.

Dynamically populate a button value android

I have seen lots of example to which one use a if condition or a case statement to programmatically change the conditions of elements...yadda yadda. I need to change the value of a button based on what the user clicks. Below is the code that I currently have.
Button btnOpenPopup = (Button)findViewById(R.id.polarity);
btnOpenPopup = (Button) findViewById(R.id.color);
final Button finalBtnOpenPopup = btnOpenPopup;
btnOpenPopup.setOnClickListener(new Button.OnClickListener(){CONTINUES TO OTHER FUNCTIONS }
I basically need to know what button was pressed. Then dynamically populate it into findViewById() function. i.e.
btnOpenPopup = (Button) findViewById(R.id.DYNAMTICVALUEOFBUTTONUSERHASPRESSED);
This way by the time it gets to the final Button part of the code it will have the value to which the user clicked on. Code works if I only want to have one button or a page mile deep in different configuration (not ideal).
All the examples I have seen so far are after the user clicks the button (which is what I want) but they name the buttons name statically like above code shows but very much static.
Hope that all makes sense.
UPDATE:
I think I may have confused the situation. Below is the remaining code. Hopefully this will provide context. The btnOpenPopup needs to remain the same as it's used in the call to execute the command for a new window to actually popup. Hopefully this will provide a bit more context for what I'm trying to achieve.
final Button finalBtnOpenPopup = btnOpenPopup;
btnOpenPopup.setOnClickListener(new Button.OnClickListener(){
#Override
public void onClick(View arg0) {LayoutInflater layoutInflater = (LayoutInflater)getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = layoutInflater.inflate(R.layout.meditationpopup, null);
//set the title of the popup
TextView titletext = (TextView) popupView.findViewById(R.id.chakratitle);
titletext.setText(activityName);
if (activityName.equals("Root"))
{
switch (arg0.getId())
{
case R.id.color:
//Rename the string so to get the value from the string xml
String stringName = activityName.toLowerCase().replaceAll(" ","")+"color";
TextView desctext = (TextView) popupView.findViewById(R.id.popupDesc);
desctext.setText(getString(getStringResource(getApplicationContext(),stringName)));
break;
case R.id.polarity:
//Rename the string so to get the value from the string xml
String polarityString = activityName.toLowerCase().replaceAll(" ","")+"polarity";
TextView polarityDesc = (TextView) popupView.findViewById(R.id.popupDesc);
//polarityDesc.setText(activityName);
polarityDesc.setText(getString(getStringResource(getApplicationContext(),polarityString)));
break;
}
}
I think
Button btnOpenPopup = (Button)findViewById(R.id.polarity);
btnOpenPopup = (Button) findViewById(R.id.color);
should be
Button btnOpenPopupFirst = (Button)findViewById(R.id.polarity);
Button btnOpenPopupSecond = (Button) findViewById(R.id.color);
you should declare different different button for diffrerent findviewbyid
also in my eclipse it is not accepting
btnOpenPopup.setOnClickListener(new Button.OnClickListener()
instead it works with
btnOpenPopup.setOnClickListener(new View.OnClickListener() {}
and you need to provide more clear view of what you want to perform
new thoughts,try doing this:
btnOpenPopupFirst.setOnClickListener(this);
btnOpenPopupSecond.setOnClickListener(this);
then option will come on both the above code lines
The method setOnClickListener(View.OnClickListener) in the type View is not applicable for the arguments (MainActivity)
choose this
let MainActivity implement OnClickListener
then this option will come
The type MainActivity must implement the inherited abstract method View.OnClickListener.onClick(View)
choose
add unimplemented method
now
#Override
public void onClick(View v)
will be created
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.polarity:
Toast.makeText(getApplicationContext(), "btnOpenPopupFirst(polarity) is pressed", Toast.LENGTH_SHORT).show();
//other code to be performed regarding this button
break;
case R.id.color:
Toast.makeText(getApplicationContext(), "btnOpenPopupSecond(color) is pressed", Toast.LENGTH_SHORT).show();
//other code to be performed regarding this button
default:
break;
}
}
And post your views after implementing this way.
int[] id={R.id.button1,R.id.button2};
Button b=(Button)findViewById(id[i]);
The onClick method in Button.OnClickListener has a View parameter... you can call getId() on that view to get the id of that button that was clicked on.
It doesn't make too much sense to me. If what you really want is this:
btnOpenPopup = (Button) findViewById(R.id.DYNAMTICVALUEOFBUTTONUSERHASPRESSED);
All you need to do is set your value in the onClick(View view) method of your OnClickListener
public void onClick(View view) {
btnOpenPopup = (Button)view;
}

How to identify the button clicked from a dynamically generated table

I am populating a table dynamically from a string array.Each row of the table also has a plus and minus button to increment/decrement the value of one column. These buttons are also dynamically created like in the code below. Here how can I detect the exact button upon clicking. i.e; if I click on the '+' button of the 2nd row, how can I get the id of the button clicked for further processing.
plusButton= new Button(this);
minusButton= new Button(this);
createView(tr, tv1, names[i]);
createView(tr, tv2, (String)(names[i+1]));
minusButton.setId(i);
minusButton.setText("-");
minusButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
plusButton.setId(i);
plusButton.setText("+");
plusButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));`
You can set an onClickListener listener for each button. Use the id of the button from view.getId() method on your onClick() method to identify the button click.
You can add separate listeners for each button like here (assuming that the id you are setting for each button corresponds to a row)
minusButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
// Do some operation for minus after getting v.getId() to get the current row
}
}
);
Edit:
I am assuming your code is like this. Correct me if there is a deviation.
Button minusButton = null;
for(int i = 0; i < rowCount; i++)
{
minusButton = new Button(this);
minusButton.setId(i);
// set other stuff and add to layout
minusButton.setOnClickListener(this);
}
Let your class implement the interface View.OnClickListener and implement the onClick() method.
public void onClick(View v){
// the text could tell you if its a plus button or minus button
// Button btn = (Button) v;
// if(btn){ btn.getText();}
// getId() should tell you the row number
// v.getId()
}
You could do with tags: minusButton.setTag("-") and plusButton.setTag("+").
In your clickListener just get it from your button with view.getTag().
Then switch between your actions comparing the string tag.
Edit:
ID's "should" be unique. The setTag() method may help you if setId() doesn't work for you.

Some alternative to hundreds of buttons

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.

Categories

Resources