I've got a view which uses an AsyncTask to make a dynamic table. The only trouble is that during this I create some checkboxes, but once the user has checked them I want to disable the box. But due to the dynamic way they were created I can't get the reference to set them disabled.
So here is how I create the buttons in a loop:
while(it.hasNext()){
if(checkStatus(it.next())){
myCheckbox.setChecked(true);
myCheckbox.setEnabled(false);
}else{
myCheckbox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
buyU asyncTask = new buyU();
asyncTask.execute("value1");
}
});
}
}
So when the button is pressed my asyncTask runs. But I can't modify the checkbox as I don't have the reference for it. I can't pass a reference I don't think as I'm using the passing parameters to send a string with a few values. So I was thinking the easiest way was to just refresh the entire page for square one again.
What is a good way to do this?
Or alternatively can I pass the button as an object to the asyncTask as well as the string and cast them back to their types on the other end?
You can pass the Object, just add an instance variable and a constructor. Since we are executing this from onClick(), we'll cast v to a CheckBox:
Checkbox c;
public buyU (CheckBox checkbox)
{
c = checkbox;
}
#Override
protected void onPostExecute (Result result)
{
c.setChecked (false);
c.setEnabled (false);
}
Then call:
CheckBox check = (CheckBox) v;
buyU asyncTask = new buyU(check);
asyncTask.execute("value1");
If you're sure that the CheckBox should be disabled upon a click, you can skip the AsyncTask param passing and just set the CheckBox to disabled right in onClick().
public void onClick(View v) {
((CheckBox)v).setChecked (false);
v.setEnabled (false);
buyU asyncTask = new buyU();
asyncTask.execute("value1");
}
I'd also be weary of that enclosing loop, make sure it's not long running if it's running in the UI Thread.
As usual, Java classes start with a capital letter, buyU doesn't fit that specification.
Related
I wanted to know if its possible to have two onclick methods for one buttton..Im trying to have a button that can open a new activity and send a id token to the server for firebase purposes, if possible how do i go about it on android studio
I think you are getting the underlying concept wrong.
Buttons react to clicks.
The "ActionListener" that gets triggered on that click ... can do whatever it wants. There is nothing (conceptually) that prevents you in your code to just trigger various things. Of course, you have to understand what you are doing (things like: not blocking the UI thread for too long; or how to kick of things in background threads, and so on).
No. There is only one onClick method for a Button. But you can still perform two different purposes by one button.
I am using a button to hide and show a linear layout. The code is given below :
final int[] count = {2};
//here startTopics is the button....
startTopics.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(count[0] %2==0)
{
topicLin.setVisibility(View.VISIBLE);
count[0]++;
}
else
{
topicLin.setVisibility(View.GONE);
//here topicLin is the linear layout
count[0]++;
}
}
});
It is one button and so you should apply only one onClick listener which performs the buttons job.
In your onClick-method you can just call another (private) method if you want to do multiple things without sacrificing code management.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
sendTokenToServer();
// Include your code to open the activity here or outsource it again into another private method
}
});
And your method to send the token to the server:
private void sendTokenToServer() {
// Your code here.
}
I got multiple OnClickListener for 8 ImageViews with the same logic behind. OnClick Variable-Details will be shown. I tried to summarize them in a method and tried to add them in the OnCreate method with a Loop. But it did not work. Now I have 8 listeners and also 8 addListener at onCreateMethod.
Is there a more elegant way?
private void addListenerCal1Arrow() {
ivCalArrow1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!cal1Clicked) {
cal1Clicked = true;
ivCalArrow1.setImageResource(R.drawable.arrow_symbol_up);
tvDescription1.setVisibility(View.VISIBLE);
} else {
cal1Clicked = false;
ivCalArrow1.setImageResource(R.drawable.arrow_symbol_down);
tvDescription1.setVisibility(View.GONE);
}
}
});
}
more explanation:
I got an experiment Fragment, where i can add 8 Variables max. Each variable has several textviews and also an ImageView, which holds further information about the variable. when the ImageView is Clicked it shall show the information. I got an container class holding all the widgets of a variable, like the textviews and the imageview and also the description which shall be displayed when its clicked
There are 2 level to summrize this code
1- use 1 onClick() for all ImageViews: this involves
1.a implementing OnClickListener and not using anonymous inner class
make your activity or fragment implements OnClickListener and override onClick()
public class MyActivity extends Activity implements OnClickListener {
//class implementation
#override
public void onClick(View view){
}
}
use this as OnClickLister for method setOnClickListener():
ivCalArrow1.setOnClickListener(this);//this here refers to MyActivity
ivCalArrow2.setOnClickListener(this);//this here refers to MyActivity
//and so on ...
b. recognize the click source (which ImageView) generated the action)
you will need to compare view id with the 8 ImageViews id and execute proper code based on that:
#override
public void onClick(View view){
if(view.getId() == ivCalArrow1.getId()){
//do what needed on ivCalArrow1
}else if(view.getId() == ivCalArrow2.getId()){
//do what needed on ivCalArrow2
}
//and so on ... for 3 4 5 6 7 8
}
2- make onClick() general to handle the click properly: this involves using arrays instead of single variables named with 1 2 3, like cal1Clicked cal2Clicked ... or tvDescription1, tvDescription2 ...
this can be done in several ways, it could be complex to understand or maintain, so try to make it clear
you might need a Map where ImageView.getId as key and some value based on what you need
for example,
boolean variables calXClicked may be you can use a HashMap, that the key is an identifier for calX and the value is boolean for the clicked status
from my understanding the identifier for cal1Clicked is the imageView itself ivCalArrow1 so:
declare this class-scope
HashMap<int, boolean> calClickedStatus = new HashMap();
an at onCreate() add this:
//assuming all boolean values are false on first create of activity
calClickedStatus.put(ivCalArrow1.getId,false);
calClickedStatus.put(ivCalArrow2.getId,false);
calClickedStatus.put(ivCalArrow3.getId,false); // and so on
now at onClick() you will use view.getId as key to lookup other data needed
no need to find what is the source of the click, because you will look it up using the key (view.getId)
#override
public void onClick(View view){
if (!calClickedStatus.get(view.getId())) {
calClickedStatus.put(view.getId(), true);
//the view here is actually the clicked ImageView, so just cast it and use it, replace this
//ivCalArrow1.setImageResource(R.drawable.arrow_symbol_up);
//with this
((ImageView)view).setImageResource(R.drawable.arrow_symbol_up);
//now for this, you may want to use an array of TextView to hold tvDescription1, tvDescription2 ...
//and make a map to link each tvDescriptionX to the index of licked image
tvDescription1.setVisibility(View.VISIBLE);
} else {
//do same changes here too
calClickedStatus.put(view.getId(), false);
ivCalArrow1.setImageResource(R.drawable.arrow_symbol_down);
tvDescription1.setVisibility(View.GONE);
}
}
as i mentioned earlier this could be complex and might be hard to explain
and it could be done in may ways, so this is just to guide you on the concept and the rest is up to you
You can define in your layout for each View the following:
android:onClick="myClickFct"
android:clickable="true"
and also in the class which loads the layout the method:
public void myClickFct(View view){
...
}
I've got very very basic problem in Java (Android) writing. Here it is, I've got code:
public void WriteValue (View sender){
Button bt=(Button)sender;
}
WriteValue is performed, when user click button. And now I want to compare button which user clicks, with button that Id I know. Something like
if(UserButton==ClearButton) Display.setText("0");
Thanks for help
Tux:)
You could just compare ids.-
public void WriteValue (View sender) {
Button bt = (Button)sender;
if(bt.getId() == R.id.clearButtonId) {
Display.setText("0");
}
}
step 1 : make your Class implement OnClickListener
step 2 :
// global variable
Button btOne ,bTwo;
step 3 :
// in onCreate() method
btOne = (Button)findViewById(R.id.btOne);
btTwo = (Button)findViewById(R.id.btTwo);
btOne.setOnClickListener(this);
btTwo.setOnClickListener(this);
step 4 : implement method from interface
puvlic void onClick(View v)
{
if(v==btOne)
{
// do work for btone
}
if(v==btTwo)
{
// do work for btTwo
}
}
You don't need to cast the View to a Button here. You can simply get the id of the View clicked which is the param sent to the function (assuming this is an onClick() function as defined in xml or by setting the listener in Java). So it could be something like this
public void WriteValue (View sender)
{
int id = sender.getId(); // get the id of the View clicked
swith (id) // switch logic on that id
{
case (R.id clearButtonId): // if the clearButton was clicked do this
Display.setText("0");
break;
default:
Display.setText("Some other String);
break;
}
}
You could also use if/else instead of a switch but this is more readable, IMHO. This easily allows you to add more logic for other Buttons.
Also consider using Java naming conventions. According to this code, I assume Display is a TextView or EditText so it should start with a lower-case letter (ex. display).
I might be on the wrong track here, and should be thinking events/publish-subscriber, if so, please enlighten me.
I have an android project running, where I have a layout which acts as an on-screen menu. Implemented in several activities/"parent-views" with the use of '< include>'. Working nicely.
Now, some of the functionality is general and global. Like I have an "add"-button, which does something, that it should always do. Then I'd like the possibility to customize what it does in addition to this, based on the activity where the action originated.
I have seperated menulogic in a simple java class, with the constructor taking an activity as a parameter. From here, I can attach clicklisteners to the buttons in the menu fine, and do stuff on click.
What I'd like is something like:
private void addBtn(String text, String path) {
LinearLayout ll = (LinearLayout) parentActivity.findViewById(R.id.dynamicButtonLayout);
Button newButton = new Button(parentActivity);
newButton.setText(text);
newButton.setTag(path);
newButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
//Do Stuff.
fireDoneHandlingButtonClick();
} catch (Exception e) {
}
}
});
}
And then have a way of handling this method in the parent activity. Should I be thinking of events, or should I be thinking of a way to add a method as an argument to the addBtn method from the activity, which can be fired from inside the click-listener?
Look at How To Implement Your Own Listener in Android or Fire and Forget Messages (events) in Android
I have an android app which is already handling changes for orientation, i.e. there is a android:configChanges="orientation" in the manifest and an onConfigurationChange() handler in the activity that switches to the appropriate layout and preps it. I have a landscape / portrait version of the layout.
The problem I face is that the activity has a dialog which could be open when the user rotates the device orientation. I also have a landscape / portrait version of the dialog.
Should I go about changing the layout of the dialog on the fly or perhaps locking the activity's rotation until the user dismisses the dialog.
The latter option of locking the app appeals to me since it saves having to do anything special in the dialog. I am supposing that I might disable the orientation when a dialog opens, such as
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
and then when it dismisses
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
Would that be a sensible thing to do? If the screen orientation did change while it was locked, would it immediately sense the orientation change when it was unlocked?
Are there alternatives?
I would recommend not turning off the screen rotation, instead of this handle the configuration changes for the Dialog. You could use one of these two approach for this:
The first one is using a flag variable in onSaveInstanceState(outState) method, and restore the dialog onCreate(bundle) method:
in this example my flag variable is called 'isShowing Dialog', when the onCreate method is called by the android System for first time, the bundle argument will be null and nothing happens. However when the activity it's recreated by a configuration change (screen rotation), the bundle will have the boolean value isShowing Dialog, previously saved by the inSaveInstanceState(...) method, so if the variable gets true the dialog is created again, the trick here is set the flag in true when the dialog get showing, and false when it's not, is a little but simple trick.
Class MyClass extends Activity {
Boolean isShowingDialog = false;
AlertDialog myDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
if(savedInstanceState!=null){
isShowingDialog = savedInstanceState.getBoolean("IS_SHOWING_DIALOG", false);
if(isShowingDialog){
createDialog();
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean("IS_SHOWING_DIALOG", isShowingDialog);
super.onSaveInstanceState(outState);
}
#Override
protected void onPause() {
if(myDialog!=null && myDialog.isShowing()) {
myDialog.dismiss();
}
}
private void createDialog() {
AlertDialog.Builder dialog_builder = new AlertDialog.Builder(this);
dialog_builder.setTitle("Some Title"):
... more dialog settings ...
myDialog = dialog_builder.create();
myDialog.show();
isShowingDialog = true;
}
private void hideDialog(){
myDialog.dismiss();
isShowingDialog = false;
}
}
The second approach is to use the ability of the fragments components to retain its states, the main idea is create the dialog inside a fragment, there is the problem about detach and reattach the fragment during the configuration changes (because you need dismiss and show the dialog correctly), but the solution is very similar to the first approach. The advantage of this approach is that if you have an AlertDialog with a couple of configurations, when the fragment is recreated there is not needed to create and setting up the dialog again, only make it show() and the AlertDialog state is maintained by the fragment.
I hope this helps.
I suggest your Dialog should override onSaveInstanceState() and onRestoreInstanceState(Bundle) to save its state into a Bundle.
You then override those methods in your Activity, checking if the Dialog is shown and if so - calling the dialog's methods to save and restore it's state.
If you are displaying this dialog from a fragment, you will want to override OnActivityCreated(Bundle) instead of OnRestoreInstanceState.
For a source example see the built-in clock app provided with Android, where the SetAlarm Activity handles the TimePickerDialog this way.
If you are handling orientation changes yourself, then here is an approach.
I won't claim that this is an elegant solution, but it works:
You can keep track of whether the dialog has an active instance inside the dialog class itself, by using a static variable activeInstance, and overriding onStart() to set activeInstance = this and onCancel() to set activeInstance = null.
Provide a static method updateConfigurationForAnyCurrentInstance() that tests that activeInstance variable and, if non-null, invokes a method activeInstance.reInitializeDialog(), which is a method that you will write to contain the setContentView() call plus the code that wires the handlers for the dialog controls (button onClick handlers, etc. - this is code that would normally appear in onCreate()). Following that, you would restore any displayed data to those controls (from member variables in your dialog object). So, for example, if you had a list of items to be viewed, and the user were viewing item three of that list before the orientation change, you would re-display that same item three at the end of updateConfigurationForAnyCurrentInstance(), right after re-loading the controls from the dialog resource and re-wiring the control handlers.
You would then call that same reInitializeDialog() method from onCreate(), right after super.onCreate(), and place your onCreate()-specific initialization code (e.g., setting up the list of items from which the user could choose, as described above) after that call.
This will cause the appropriate resource (portrait or landscape) for the dialog's new orientation to be loaded (provided that you have two resources defined having the same name, one in the layout folder and the other in the layout-land folder, as usual).
Here's some code that would be in a class called YourDialog:
ArrayList<String> listOfPossibleChoices = null;
int currentUserChoice = 0;
static private YourDialog activeInstance = null;
#Override
protected void onStart() {
super.onStart();
activeInstance = this;
}
#Override
public void cancel() {
super.cancel();
activeInstance = null;
}
static public void updateConfigurationForAnyCurrentInstance() {
if(activeInstance != null) {
activeInstance.reInitializeDialog();
displayCurrentUserChoice();
}
}
private void reInitializeDialog() {
setContentView(R.layout.your_dialog);
btnClose = (Button) findViewById(R.id.btnClose);
btnClose.setOnClickListener(this);
btnNextChoice = (Button) findViewById(R.id.btnNextChoice);
btnNextChoice.setOnClickListener(this);
btnPriorChoice = (Button) findViewById(R.id.btnPriorChoice);
btnPriorChoice.setOnClickListener(this);
tvCurrentChoice = (TextView) findViewById(R.id.tvCurrentChoice);
}
private void displayCurrentUserChoice() {
tvCurrentChoice.setText(listOfPossibleChoices.get(currentUserChoice));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
reInitializeDialog();
listOfPossibleChoices = new ArrayList<String>();
listOfPossibleChoices.add("One");
listOfPossibleChoices.add("Two");
listOfPossibleChoices.add("Three");
currentUserChoice = 0;
displayCurrentUserChoice();
}
#Override
public void onClick(View v) {
int viewID = v.getId();
if(viewID == R.id.btnNextChoice) {
if(currentUserChoice < (listOfPossibleChoices.size() - 1))
currentUserChoice++;
displayCurrentUserChoice();
}
}
else if(viewID == R.id.btnPriorChoice) {
if(currentUserChoice > 0) {
currentUserChoice--;
displayCurrentUserChoice();
}
}
Etc.
Then, in your main activity's onConfigurationChanged() method, you would just invoke YourDialog.updateConfigurationForAnyCurrentInstance() whenever onConfigurationChanged() is called by the OS.
Doesn't seem the title was ever resolved (Google Necro Direct).
Here is the solution, matching the request.
When your activity is created, log the screen orientation value.
when onConfiguration change is called on your activity, compare the orientation values. if the values don't match, fire off all of your orientation change listeners, THEN record the new orientation value.
Here is some constructive code to put in your activity (or any object that can handle configuration change events)
int orientation; // TODO: record orientation here in your on create using Activity.this.getRequestedOrientation() to initialize!
public int getOrientation(){return orientation;}
public interface OrientationChangeListener {
void onOrientationChange();
}
Stack<OrientationChangeListener> orientationChangeListeners = new Stack<>();
public void addOrientationChangeListener(OrientationChangeListener ocl){ ... }
public void removeOrientationChangeListener(OrientationChangeListener ocl){ ... }
That's the basic environment. Here's your executive:
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (orientation != newConfig.orientation)
for (OrientationChangeListener ocl:orientationChangeListeners) ocl.onOrientationChange();
orientation = newConfig.orientation;
}
In YOUR code model, you may need to send the new configuration, with the event, or the two orientation values with the event. However, Activity.this.getOrientation() != Activity.this.getRequestedOrientation() during event handling (because we are in a logical state of change between two logical values).
In review of my post, i have determined that there could be some synchronization issues, with multiple events! This is not a fault of this code, but a fault of "Android Platform" for not having defacto orientation sense handlers on every window, thusly trashing the polymorphic benefits of using java in the first place..
See the answer from Viktor Valencia above. That will work perfectly with the slight adjustment that you move the createDialog() to onResume.
#Override
protected void onResume() {
super.onResume();
if(isShowingDialog){
createDialog();
}
}
Fetch the boolean isShowingDialog value at onCreate, as suggested, but wait for onResume to display the dialog.