Retrieving information from custom dialog called from within non-Activity class - android

I am working on a board game app (similar to chess). I have the activity GameBoardActivity which listens for clicks on a GridView, and at each click calls functions from a class Game to handle what should occur.
Within the class Game is the data about where pieces are and the method Move(int xFrom, int yFrom, int xTo, int yTo) where piece movement is handled.
For certain movements that a user may specify (e.g. that the piece at xFrom, yFrom should go to xTo, yTo) I want to provide them with a choice between two options. You can imagine that one choice is to go there normally, and the other is to go there as a transformed piece. To do this I want to display a custom dialog that presents the two choices for the user to click.
My custom Dialog class is given below:
public class CustomDialog extends Dialog implements View.OnClickListener{
Context mcontext;
Button button1;
Button button2;
int choice; //holds value of user's choice
public CustomDialog(Context context) {
super(context);
mcontext = context;
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
choice = 0; //no choice yet
}
public void setLayout(){
this.setContentView(R.layout.custom_dialog);
button1.setOnClickListener(this);
button2.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button1:
choice = 1;
break;
case R.id.button2:
choice = 2;
break;
}
dismiss();
}
}
What I'm not clear on is how to pass the information about the user's choice back to the class Game.
Any help is greatly appreciated.

Save a reference to parent Activity via the constructor of the dialog:
private final MyActivity mCaller;
public CustomDialog(MyActivity caller) {
super(caller);
mCaller = caller;
//.......
}
Pass values to calling activity by invoking its methods:
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button1:
mCaller.setChoice(1);
break;
case R.id.button2:
mCaller.setChoice(2);
break;
}
dismiss();
}

Create a bean class for storing the button actions ....
While clicking the events store it in a bean
In a game class u access the action values for button from the bean class

Related

Button not responding to click event

Below is what i have tried. "Forward" class extends Activity. It contains two buttons. In this class , we create two objects of "Collector" class using for loop. In the first iteration of the loop we create first button. In the second, we create one more button. we set "OnClickListener" for both the buttons. but only the second button responds for the click. First button doesnt respond to a click. I'm trying to use same variable name (b1) - I want to stick to OO Principle by not creating separate object for achieving my goal. - Also I'm expecting properties of 2 Objects as separate entity.Please help me. regards.
Forward.java (is an Activity, contains two buttons):
below is a for loop in which i create 2 objects of collector class.
for (int i = 0; i < 2; i++) {
new Collector(this, i);
}
Collector.java :
public class Collector {
Forwarder f;
int n;
Button b1;
public Collector(Forwarder caller, int i) {
f = caller;
n = i; // 0 or 1
f.setContentView(R.layout.forwarder);
switch(n)
{
case 0:
b1 = (Button) f.findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// get a new Contact
Intent i = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
f.startActivityForResult(i, 1);
// onActivityResult has to be implemented in f because
// f extends Activity class
}
});
break;
case 1:
b1 = (Button) f.findViewById(R.id.button2);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// get a new Contact
Intent i = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
f.startActivityForResult(i, 1);
}
});
break;
default:
}
}
}
You gave Your button a new id.
first, You wrote:
b1 = (Button) f.findViewById(R.id.button1);
at the second switch You wrote:
b1 = (Button) f.findViewById(R.id.button2);
public class Collector {
Forwarder f;
int n;
Button b1;
public Collector(Forwarder caller, int i) {
f = caller;
n = i; // 0 or 1
f.setContentView(R.layout.forwarder);
switch(n)
{
case 0:
b1 = (Button) f.findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// get a new Contact
Intent i = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
f.startActivityForResult(i, 1);
// onActivityResult has to be implemented in f because
// f extends Activity class
}
});
break;
case 1:
b1 = (Button) f.findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// get a new Contact
Intent i = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);
f.startActivityForResult(i, 1);
}
});
break;
default:
}
}
}
You have mistaken in your switch case you named both of buttons b1 when the second object starts to be create b1 is no longer Button1 now it is Button2 so you set onclick listener only for Button2 use a custom class for your buttons or try to declear new objects like b2 b3
good luck soheil
Check the button names. They are the same (b1). Change the second variable name and everything should work perfectly. Damn copy-paste :P
I don't have the answer on why such behavior but it will definitively help you if you add few things as a part of clarification or rephrase your question else people consider it as some novice mistake.
- Clearly mention that you know that you are trying to use same variable name (b1)
- You want to stick to OO Principle by not creating separate object for achieving your goal.
- Also you can mention that you are expecting properties of 2 Objects as separate entity.
Hope it helps. All the best.

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;
}

Keeping multiple OnClickListeners in one class

I am kinda new to Android and it would improve my application a lof if I coul keep several OnClickListenres in one class. What I am thiking of is something like this :
Public class OnClickListeners {
public Button.OnClickListener open;
public Button.OnClickListener doSomethingElse;
public Button.OnClickListener etc;
public OnClickListeners() {
open = new Button.OnClickListener()
{
public void onClick(View view)
{
DetailList.SetId(view.getId());
Intent intent = new Intent(view.getContext(), DetailList.class);
startActivityForResult(intent, 100);
}
};
}
}
So I can then reference it in other class B like this
button1.setOnClickListener(OnClickListeners.open);
Any though how to do it?
Android SDK seems to be against me as I can figure it out now for about 2 days now...
Thanks for any advices and help
There is a sleek way to consolidate all your anonymous classes into one and switch on the view. This works best if you know ahead of time which buttons will be using the clicklistener :
public class AndroidTestClickListenerActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new MyClickListener());
Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new MyClickListener());
Button button3 = (Button) findViewById(R.id.button3);
button3.setOnClickListener(new MyClickListener());
}
}
class MyClickListener implements View.OnClickListener {
#Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.button1:
// do soemthign for button1
break;
case R.id.button2:
// do something for button2
break;
case R.id.button3:
// do something for button3
break;
default:
// do something for any other button
}
}
}
You can write
button1.setOnClickListener(new OnClickListeners().open);
instead, but this seems an odd architecture for me. I'd suggest you to keep 1 listener in 1 file, having all of them in 1 package, and use like
button1.setOnClickListener(new OpenListener());
The problem of you approach is that usually listeners have to manipulate some data that is part of the class where UI elements are.
If you take listeners out and put them in a separate class, you will also have to provide a lot of references to objects where data to be manipulated is. This will create a lot of interdependent classes, which will not be nice.
IMHO the cleanest way is to use anonymous inner classes.
You can, but you have to declare the OnClickListener as static if you would like to use it in this manner.
public static Button.OnClickListener openListener = new Button.OnClickListener() {
public void onClick(View view) {
}
};
Then you can use:
button1.setOnClickListener(OnClickListeners.openListener);
As noted by other user - this approach is most like bad. You should handle view listeners on the same view and then maybe call another method like openActivity(). I would not do this - you are also openning an activity from another activity, this will probably don't work at all or will mess up the activity history stack
As none of the solutions actually did what I wanted to achieve - I needed a second (or multiple) onClickListener that did not override the onClickListeners that were already assigned to the control.
Here is the java class that I wrote for that purpose:
https://gist.github.com/kosiara/c090dcd684ec6fb2ac42#file-doubleclicklistenerimagebutton-java
public class DoubleClickListenerImageButton extends ImageButton {
View.OnClickListener mSecondOnClickListener;
public DoubleClickListenerImageButton(Context context) {
super(context);
}
[...]
public void setSecondOnClickListener(View.OnClickListener l) {
mSecondOnClickListener = l;
}
#Override
public boolean performClick() {
if (mSecondOnClickListener != null)
mSecondOnClickListener.onClick(this);
return super.performClick();
}
#Override
public boolean performContextClick() {
if (mSecondOnClickListener != null)
mSecondOnClickListener.onClick(this);
return super.performContextClick();
}
}

ParseInt Exception

I am creating a small calc app with EditText views and Im running into an runtime exception when the user leaves an EditText view empty causing the ParseInt to try and Parse nothing. Ive read that I need to 'Try' and 'Catch' this error before it occurs, but Im unsure of where and how to do this!
Any advice is much appreciated!
Here is my code:
public class HandlerExamples extends Activity implements OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.testButton);
button.setOnClickListener(this);
public void onClick(View v) {
String a,b,t;
double vis;
EditText txtbox1 = (EditText)findViewById(R.id.A);
EditText txtbox2 = (EditText)findViewById(R.id.B);
EditText txtbox3 = (EditText)findViewById(R.id.t);
TextView tv = (TextView) findViewById(R.id.Answer);
a = txtbox1.getText().toString();
b = txtbox2.getText().toString();
t = txtbox3.getText().toString();
vis = ((Integer.parseInt(a)*1) + (Integer.parseInt(b)*2)) / (Double.parseDouble(t));
tv.setText(double.toString(vis));
}
}
Thanks so much!
public void onClick(View v) {
int id = v.getId();
switch(id){
case R.id.xx:
//do things xx click
break;
case R.id.yy:
//do things yy click
break;
}
}
you can get the view id to know whick widget was clicked.
Changwei Yao defined one way you can do this, but here's the way most Android programmers would do this (programmatically), since it's a little easier to read and figure out what your widgets are doing:
But first, remove the implements OnClickListener from your Activity, as it's not needed.
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// what you want your button to do when clicked
}
}
editText.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// what you want your EditText to do when clicked
// (such as editText.setText(""))
}
}
Another way to do the same thing is to define android:onClick="insert_method_name_here" for the widgets that you want perform an action when clicked. In your case, in your main.xml (since that's what you're using in your Activity), you could write something like...
<Button android:id="#+id/testButton"
(other attributes you wish to apply to the button)
android:onClick="buttonAction" />
<EditText
(other attributes)
android:onClick="textAction" />
And then, in your Activity, you define the methods buttonAction(View v) and textAction(View v). Note that these methods must be public void, and must take the sole argument View v.
(One advantage of the XML method is that you don't necessarily have to define an android:id attribute for these widgets, unless you need to be able to manipulate them or extract information from them in your code (which means you will need to define an android:id for your EditText since you'll likely want the user's input))
If you only need to exclude the empty text field then hotveryspicy's solution is probably the quickest. For a secure solution: catching the NumberFormatException will filter anything that can not be converted to an integer.
int vis;
try {
vis = Integer.parseInt(a);
}
catch(NumberFormatException nfe) {
Log.e(TAG,"trying to convert:"+a+" to integer failed");
vis = 0;
}

ClickListener current target

EditText etHomePhone = (EditText)findViewById(R.id.et_pi_home_phone);
EditText etMobilePhone = (EditText)findViewById(R.id.et_pi_home_phone);
etHomePhone.setOnClickListener(showPopUpClickListener);
etMobilePhone.setOnClickListener(showPopUpClickListener);
private View.OnClickListener showPopUpClickListener = new View.OnClickListener() {
public void onClick(View v) {
/* I like to get both EditText.getText().toString() value in this one ClickListener
is it Possible, there is something in ActionScript call event.currentTarget...
*/
}
};
If you declare your etHomePhone and etMobilePhone variables as final and define your OnClickListener inline in the same method, then you can refer to those variables directly. Like so:
final EditText etHomePhone = (EditText)findViewById(R.id.et_pi_home_phone);
final EditText etMobilePhone = (EditText)findViewById(R.id.et_pi_home_phone);
View.OnClickListener showPopUpClickListener = new View.OnClickListener() {
public void onClick(View v) {
String home = etHomePhone.getText().toString();
String mobile = etMobilePhone.getText().toString();
// Do something with home and mobile
}
};
etHomePhone.setOnClickListener(showPopUpClickListener);
etMobilePhone.setOnClickListener(showPopUpClickListener);
EDIT:
If you only want to get the text for the EditText that was clicked instead of both of them, then you can just cast the View that it delivered via onClick(View v):
public void onClick(View v) {
EditText editText = (EditText)v;
String phoneNumber = editText.getText().toString();
// Do something with phoneNumber
}
This is a snippet, so I can't see the context but you can structure a single OnClickListener to catch all events in your activity. First, your activity will need to implement the OnClickListener interface:
public class YourActivity extends Activity implements OnClickListener {...
In the OnCreate() method, register each UI element which should respond to clicks like this:
yourObject.setOnClickListener(this);
Next, for the activity's onClick() method, create a switch structure using R.id like this:
#Override
public void onClick(View view) {
switch(view.getId()){
case R.id.A_UI_Element:
//do what you need for this element
break:
case R.id.A_Different_UI_Element:
//do what you need for this element
break;
//continue with cases for each element you want to be clickable
}
}
Don't forget the break at the end of each case.
One thing I noticed in your code: both editText declarations refer to the same resource. This gives you two handles to the same UI element, not 2 different elements.

Categories

Resources