Basing on the RoboGuice API for firing an event, inside my CustomButtonView implementation I have did like so:
#Override
public void onClick(View v) {
CommonApplication.getInstance().fireEvent(new InteractionButtonClicked());
// setSelected();
}
public class InteractionButtonClicked
{
public String getRef()
{
return (String)getTag();
}
}
// handle the click event
protected void handleClick(#Observes InteractionButtonClicked button) {
if (getTag().equals(button.getRef())) {
//do A
} else {
//do B
}
}
However, handleClick does not get called in this context=> when I set an #Observer in the main activity it's containing method does get called.
I'm trying to understand why, and if there is an option to observe the event in the Customview context...
Related
I have been looking for my question on Google and inside the forum but I cannot an answer so far. I am using android studio to code an app in Java
The thing is : inside a class, I have overrided the OnClick() method because I have to implement a lot of views.
Now I want to call a function just before OnClick() is called.
What I mean is, for instance, if the user taps on a button, before OnClick() is called I want one of my methods to be called.
Does anyone know how to do this ?
Thank you in advance
I want to call a function just before OnClick() is called
You can use a logic inside onClick() like,
if(userhaspermission())//your method to check if the user has permission
{
//your onclick operation code
}
Make your checking permission method with return type as boolean
Implement your custom OnClickListener as follows
public abstract class MyOnClickListener implements OnClickListener {
#Override
public void onClick(View v) {
//Do common action
if(condidtionSatisfied){
performClick(v);
}
}
public abstract void performClick(View v);
}
Set onClickListener to any component as follows:
button.setOnClickListener(new MyOnClickListener() {
#Override
public void performClick(View v) {
//Execute post click action
}
});
This will ensure your common code will be called for all the views and it would be much cleaner approach.
Override the onClick() method and write your first logic which you want.
Write your own Listener like Sagar said
This logic is quite similar to Sagar's Answers.
Write abstract class as given below
public abstract class OnClick implements View.OnClickListener {
public void beforeClick(View v) {
}
#Override
public void onClick(View v) {
beforeClick(v);
performClick(v);
afterClick(v);
}
public void performClick(View v) {
}
public void afterClick(View v) {
}
}
NOTE : See in above code it implements View.OnClickListener, so this logic will works for views which extends View super class. If you want above logic for object's which needs Dialog interface onClick then you need to modify it for DialogInterface.OnClickListener.
So you can use above logic as below
//Let say you need it for button with id button
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClick() {
#Override
public void beforeClick(View v) {
Toast.makeText(MainActivity.this, "Before", Toast.LENGTH_SHORT).show();
}
#Override
public void performClick(View v) {
Toast.makeText(MainActivity.this, "Click", Toast.LENGTH_SHORT).show();
}
#Override
public void afterClick(View v) {
Toast.makeText(MainActivity.this, "After", Toast.LENGTH_SHORT).show();
}
});
I'm doing some Android development and I have an object, which doing a specific task. When that task is done I need to inform my main method (Main Activity), which is constantly running, that the process has been finished and pass some information about it.
This may sound a bit unclear, so I'll give you an example:
Take a look at the setOnClickListener() method in Android:
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
//This method is called on click
#Override
public void onClick(View v) {
//The View is passed in an anonymous inner class
}
});
It waits for a button to be clicked and calls the onClick(View v) method. I am seeking to achieve the same code structure. How to do this?
You mentioned "process". If you are truly doing something in a different process, then you need to look at interprocess communications (IPC). Otherwise, you can use an interface:
Create a class called MyListener:
public interface MyListener {
void onComplete();
}
In your class that will notify your activity:
MyListener myListener;
public void setMyListener(MyListener myListener){
this.myListener = myListener;
}
Then, when you are ready to notify your main activity, call this line:
myListener.onComplete();
Last, in your MainActivity implement MyListener:
public class MyListener extends Activity implements MyListener {
///other stuff
#Override
public void onComplete(){
// here you are notified when onComplete it called
}
}
Hope this helps. Cheers.
This is exactly Listener pattern that you use with views in android. What you want to do is declare an interface in your class that's doing the job, and pass an instance of this interface. Raw example:
TaskDoer.java:
public class TaskDoer {
public interface OnTaskDoneListener {
void onDone(Data data);
}
public void doTask(OnTaskDoneListener listener) {
// do task...
listener.onDone(data);
}
}
Activity:
public void doTaskAndGetResult() {
new TaskDoer().doTask(new TaskDoer.OnTaskDoneListener() {
public void onDone(Data data) {
// do something
}
}
}
I currently have a fragment containing two spinners and I want to send the information from both spinners to MainActivity. Is this possible? While my code works when I send the information from just one spinner, as soon as I try and send the information from both spinners (per below), none of the information appears to be transmitted:
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
onNumberInPartyListener = (onNumberInPartyListener) activity;
onMethodOfSplitListener = (onMethodOfSplitListener) activity;
}
catch (Exception ex){}
}
Do I need to create two onAttach methods, two fragments or is there another way?
Thanks
Update:
So I ended up doing away with the above and instead used an 'Interface' java class to send the information from Fragment 1 to Main Activity, however now I'm having issues sending the information from Main Activity to Fragment 2.
In my Main Activity, I'm sending the information to Fragment 2 with the following code (where 'evenSplit_CalculationFragment2' is Fragment 2 and 'tellMeWhatEachPersonOwesES is the method I've implemented in Fragment 2):
//Send data to Even Split Fragment 2
evenSplit_CalculationFragment2.tellMeWhatEachPersonOwesES(eachPersonOwesESString);
And in Fragment 2 I've implemented this as follows:
//What Each Person Owes (from Main Activity)
public void tellMeWhatEachPersonOwesES (String eachPersonOwesThisESString) {
amountEachPersonOwesES.setText(eachPersonOwesThisESString);
}
However, I'm coming up with a Null Pointer exception for both of these. I've tried testing this by substituting 'eachPersonOwesThisESString' with an actual string (e.g. "test") but most baffling of all I still get a Null Pointer exception. Any help appreciated.
You should use Handler
h = new Handler() {
public void handleMessage(android.os.Message msg) {
// Getting data from Handler
tvInfo.setText("Data from Spinner1: " + msg.what);
if (msg.what == 10)
// do what you need
};
};
You can use one handler with different msg.what codes to distinguish them. Initialise it in activity and send to fragment, it will fire up when you write h.sendMessage
If I wanted to solve this problem, what I'd do is use an event bus (although if you really want, you can technically use LocalBroadcastManager with Parcelables).
With Otto event bus, it'd look like this
public enum SingletonBus {
INSTANCE;
private Bus bus;
private Handler handler = new Handler(Looper.getMainLooper());
private SingletonBus() {
this.bus = new Bus(ThreadEnforcer.ANY);
}
public <T> void postToSameThread(final T event) {
bus.post(event);
}
public <T> void postToMainThread(final T event) {
handler.post(new Runnable() {
#Override
public void run() {
bus.post(event);
}
});
}
public <T> void register(T subscriber) {
bus.register(subscriber);
}
public <T> void unregister(T subscriber) {
bus.unregister(subscriber);
}
}
public class YourFragment extends android.support.v4.Fragment {
public static class SpinnersSelectedEvent {
public String firstSpinnerData;
public String secondSpinnerData;
public SpinnersSelectedEvent(String firstSpinnerData, String secondSpinnerData) {
this.firstSpinnerData = firstSpinnerData;
this.secondSpinnerData = secondSpinnerData;
}
}
#OnClick(R.id.yourfragment_thebutton)
public void theButtonClicked() {
SingletonBus.INSTANCE.postToSameThread(new SpinnersSelectedEvent(firstSpinner.getSelectedItem(), secondSpinner.getSelectedItem()); //pseudo code on the spinner part
}
}
public class MainActivity extends AppCompatActivity {
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
//...
SingletonBus.INSTANCE.register(this);
}
public void onDestroy() {
super.onDestroy();
SingletonBus.INSTANCE.unregister(this);
}
#Subscribe
public void onSpinnersSelectedEvent(YourFragment.SpinnersSelectedEvent e) {
String firstData = e.firstSpinnerData;
String secondData = e.secondSpinnerData;
// do things
}
}
I have a Screen implementation with InputMultiplexer which is initialized in the show() method. The InputMultiplexer is initialized with InputAdapter and the Stage object.
The InputAdapter object listens for the back button.
class MyInputAdapter extends InputAdapter {
#Override
public boolean keyDown(int keycode) {
if (keycode == Keys.BACK) {
// do someting
return true;
}
return false;
}
}
class MyScreen implements Screen {
#Override
public void show() {
initInputProcessors();
}
private void initInputProcessors() {
if (backButtonInputProcessor != null) {
initInputMultiplexer();
Gdx.input.setCatchBackKey(true);
Gdx.input.setInputProcessor(inputMiltiplexer);
} else {
Gdx.input.setCatchBackKey(false);
Gdx.input.setInputProcessor(stage);
}
}
private void initInputMultiplexer() {
if (inputMiltiplexer == null) {
inputMiltiplexer = new InputMultiplexer();
inputMiltiplexer.addProcessor(backButtonInputProcessor);
inputMiltiplexer.addProcessor(stage);
}
}
}
All works fine, and the back button reacts without any problem.
The problem occurs, in the following scenario. I use admob. So when clicking an ad banner, this brings you to browser. When you are back from browser to the app, the back button is not intercepted and the application just exits.
I also tried calling the InitInputProcessors method inside the resume() method, same result.
The answer to my question on LibGDX forum has solved it. Following is the solution by skunktrader:
Try adding this to your android MainActivity
#Override
public void onResume() {
super.onResume();
theView.requestFocus();
theView.requestFocusFromTouch();
}
Where theView is the value returned from initializeForView().
Try to set your InputProcessor as null in hide() method. Like this:
#Override
public void hide() {
Gdx.input.setInputProcessor(null);
}
For example I want to execute something when user clicks on a button. Which do I use? The documentation didn't appear to make it very clear
UPDATE
A quick test shows that Widget Selected is triggered but not Default Selected.
In TasksView.main()
TasksView view = new TasksView(shell, SWT.None);
TasksController controller = new TasksController(view);
In TasksController
public class TasksController extends ControllerAbstract {
protected TasksView view;
public TasksController(TasksView view) {
this.view = view;
view.addTaskListener(new AddTaskListener());
}
protected class AddTaskListener implements SelectionListener {
#Override
public void widgetDefaultSelected(SelectionEvent arg0) {
System.out.println("Default Selected");
}
#Override
public void widgetSelected(SelectionEvent arg0) {
System.out.println("Widget Selected");
}
}
}
btw, Did I do MVC correctly?
Use widgetSelected. In fact, all the better is to simply extend SelectionAdapter and only override the widgetSelected method and completely ignore widgetDefaultSelected.
SelectionListener.widgetDefaultSelected(e) has a toolkit dependent behavior. I usually just invoke SelectionListener.widgetSelected(...). (Note that this is not the default in SelectionAdapter.widgetDefaultSelected(e) - you will have to do this yourself.