I'm using a gesture listener to monitor user's action, but when the app pops up the dialog, I don't know how to switch my gesture listener to dialog event and handle the event button (ok and cancel), can anyone give me a suggestion?
Pseudo code likes this
public class MainActivity extends FragmentActivity
implements ConnectionEventListener{
......
// when connection established,
// pop a diaglog (android native diaglog with listview and its adapter) to ask user to select ok or cancel button
#Override
public void onUpdateAlert(final int event, final String message){
}
// gesture listener
// if a dialog pops up, the pose can be used to select OK or cancel
#Override
public void onDetected(Hand pose){
}
}
The problem I have is not the button listener. Actually, I have two listeners work at the same time, one for event monitor and another for pose monitor. When an event comes, the event will pop up a dialog to select "ok" or "cancel" . In the mean time, a pose listener still works. I'd like to know when this case happens, how can I use the pose listener to select "ok" or "cancel" while the diaglod pops up?
I think we need something like this:
public static void showDialog(SomeActivity someActivity, final SomeCallback callBack {
final Dialog dialog = new Dialog(someActivity);
dialog.setContentView(R.layout.dialog_with_buttons);
// OK button ...
Button dialogButtonOk = dialog.findViewById(R.id.btn_ok);
dialogButtonOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
callBack.execute(true);
dialog.dismiss();
}
});
// Cancel button ...
Button buttonCancel = dialog.findViewById(R.id.btn_cancel);
buttonCancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callBack.execute(false);
dialog.dismiss();
}
});
dialog.show();
}
we can call the showDialog from SomeActivity like this:
showDialog(this, new SomeCallback () {
#Override
public void execute(boolean status) {
if (status) {
...
} else {
...
}
}
});
and the callback interface:
public interface SomeCallback {
void execute(boolean status);
}
good luck
the pseudo code can be like:
boolean status = false;
#Override
public void onUpdateAlert(final int event, final String message){
status = true;
// pop up the dialog
}
#Override
public void onDetected(Hand pose){
if(status) {
status = false;
...
}
}
Related
We're trying to implement a "The User is typing" message as long as a user keeps typing within a specific EditText. For example, once the user starts typing within the EditText, and as long as 2 seconds didn't pass since the last typing event, keep showing the "User is typing" message.
Any idea how to achieve that easily without blocking any threads?
Thanks!
Yohay
you can handle it by using focusChangeListener
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
//user typing
} else {
//user stop typing
}
}
});
Once user start typing , start a background thread(BT) and pass text of your edit text via Message to your BT. After every 2 seconds ping (post a message) to your Main Thread from BT. On receiving the message in MainThread pass a message containing text in your edit text to your BT. On receiving message in BT simply compare text just received to previous text passed in BT. If both the texts are same, user is not typing.
But user can start typing again any moment, so keep on playing this game in background until message is alive(neither sent nor discarded). Once message life is over kill your BT.
Edit example code
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private boolean killThread = false;
private EditText editText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.editText);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
Log.d(TAG, "onFocusChange: gained focus");
startThread(new WeakReference<MainActivity>(MainActivity.this));
}
}
});
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// for simplicity killing thread here
killThread = true;
}
});
}
private void startThread(final WeakReference<MainActivity> activityWeakReference) {
new Thread(new Runnable() {
String savedText = "";
#Override
public void run() {
do {
MainActivity activity = activityWeakReference.get();
if (null == activity) {
// Activity destroyed, killME!!!
killThread = true;
Log.e(TAG, "run: activity reference null, killing MYSELF😔😔");
} else {
if (savedText.equals(activity.editText.getText().toString())) {
Log.e(TAG, "run: user is not typing");
} else {
savedText = activity.editText.getText().toString();
Log.e(TAG, "run: user typing ");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} while (!killThread);
}
}).start();
}
}
When EditText gains focus , I am starting a Thread (passing WeakReference to Activity also) and then using WeakReference getting hold of EditText and checking its Text. For Simplicity, I am simply killing Thread on Button Click.
Code
Button mButton;
int mDefaultColor;
mButton = (Button)findViewById(R.id.buttontextcolorsent);
mDefaultColor = ContextCompat.getColor(Customise.this,R.color.white);
mButton.setBackgroundColor(mDefaultColor);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openColorPicker();
}
});
}
private void openColorPicker() {
AmbilWarnaDialog colorPicker = new AmbilWarnaDialog(this, mDefaultColor, new AmbilWarnaDialog.OnAmbilWarnaListener() {
#Override
public void onCancel(AmbilWarnaDialog dialog) {
}
#Override
public void onOk(AmbilWarnaDialog dialog, int color) {
mDefaultColor = color;
mButton.setBackgroundColor(mDefaultColor);
}
});
colorPicker.show();
}
}
This is a popular library called ambil warna which shows a colorpicker... when a user picks the color it successfully changes the color of the button... but the problem is its not permanent... like if the user exits and enters the activity again the button will turn back to its original default color... so how do i make this change permanent? and i dont want to use any kind of server database... so is it possible to make this change using SQLlite? or is there any other way?
You could just store the selected color to SharedPreferences.
PreferencaManager.getDefaultSharedPreferences()
.edit()
.putInt("button_color", newHighScore)
.apply()
This is my first android app,
I am calling function result on button click but as its call to findTimeTable takes time i want to show a progress bar but for some reason progress bar fails to show up until last moment just before the dialog box is created which defeats my purpose of showing the progress bar for that time period. In-fact that last moment is only visible when i don't set their visibility back to what it was.
public void result(View view) throws IOException {
findViewById(R.id.loadingPanel).setVisibility(View.VISIBLE);
findViewById(R.id.chooseFile).setVisibility(View.GONE);
findViewById(R.id.chooseDay).setVisibility(View.GONE);
findViewById(R.id.chooseTime).setVisibility(View.GONE);
findViewById(R.id.findFaculty).setVisibility(View.GONE);
String n = findTimetable(index_day, index_time);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("hello" +n);
builder.setCancelable(false);
builder.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i){
}
});
final Dialog mDialog = builder.create();
mDialog.show();
findViewById(R.id.loadingPanel).setVisibility(View.GONE);
findViewById(R.id.chooseFile).setVisibility(View.VISIBLE);
findViewById(R.id.chooseDay).setVisibility(View.VISIBLE);
findViewById(R.id.chooseTime).setVisibility(View.VISIBLE);
findViewById(R.id.findFaculty).setVisibility(View.VISIBLE);
}
I found a relevant answer android progress bar not showing
but as i am not familiar with threads in programming i could not implement it properly on my code.
please help.
Use an AsyncTask for the heavy comupting and add the progress bar in its Pre/Post states, and if you choose to update the GUI from there you need to run that code on the UI Thread.
Example AsyncTask:
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
// Start progressbar
}
#Override
protected String doInBackground(String... params) {
// Computing goes here
return null;
}
#Override
protected void onPostExecute(String result) {
// Stop progressbar
UpdateMyGUI();
}
#Override
protected void onProgressUpdate(Void... values) {
// Update progressbar (?)
}
}
private void updateMyGUI(){
runOnUiThread (new Runnable() {
public void run() {
// Update GUI Here.
}
});
}
I'm using setOnClickListener for listening on the click event on imageButton in two methods, but it's does not fire in my another method,my first listener firing but my second listener does not fire please see my codes :
Class FirstActivity extends BaseActivity
{
#Override
public void onCreate()
{
super.onCreate();
this.methodA();
this.methodB();
}
public void methodA()
{
ImageButton imageButton = (ImageButton) RContextHelper.getActivity().findViewById(R.id.my_location_button);
imageButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//event firing when image button touched
}
});
}
public void methodB()
{
Test test = new Test(this);
test.methodA();
}
}
class Test
{
Context con;
public Test(Context con)
{
this.con = con;
}
public void methodA()
{
ImageButton imageButton = (ImageButton) getActivity().findViewById(R.id.my_location_button);
imageButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//event does not fire when image button touched
}
});
}
protected ActionBarActivity getActivity()
{
return (ActionBarActivity) con;
}
}
As you can guess from the name setOnClickListener sets the new listener and replaces the old one. That is the case with all the set* listeners in Java. If it was addOnClickListener then you could expect that both listeners should be called.
If you want both of them to be called, you can write a composite on click listener and add both of the listeners to it and set the composite listener to the target.
class CompositeListener implements OnEventListener {
private List<OnEventListener> registeredListeners = new ArrayList<OnEventListener>();
public void registerListener (OnEventListener listener) {
registeredListeners.add(listener);
}
public void onEvent(Event e) {
for(OnEventListener listener:registeredListeners) {
listener.onEvent(e);
}
}
}
And then:
CompositeListener composite = new CompositeListener();
composite.registerListener(listener1);
composite.registerListener(listener2);
imageButton.setOnEventListener(composite);
Source
Very confusing to code with two methodA functions. You never call the second one. At least you are not showing code for that. Moreover - as has been said already - there can only be one listener.
A button triggers an action that should only be invoked once. The button is disabled and hidden in the onClick handler before the action is performed:
someButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
someButton.setEnabled(false);
someButton.setClickable(false);
someButton.setVisibility(View.GONE);
performTaskOnce();
}
});
private void performTaskOnce() {
Log.i("myapp", "Performing task");
//Do something nontrivial that takes a few ms (like changing the view hierarchy)
}
Even though the button is disabled immediately, it is nonetheless possible to trigger multiple "onClick" events by tapping multiple times very quickly. (i.e. performTaskOnce is called multiple times). Is seems that the onClick events are queued before the the button is actually disabled.
I could fix the problem by checking in every single onClick handle whether the corresponding button is already disabled but that seems like a hack. Is there any better way to avoid this issue?
The problem occurs on Android 2.3.6, I cannot reproduce it on Android 4.0.3. But given the rarity of 4.x devices it is not an option to exclude older devices.
You could set a boolean variable to true when the button is clicked and set it to false when you're done processing the click.
This way you can ignore multiple clicks and not having to disable the button possibly avoiding annoying flickering of the button.
boolean processClick=true;
someButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(processClick)
{
someButton.setEnabled(false);
someButton.setClickable(false);
someButton.setVisibility(View.GONE);
performTaskOnce();
}
processClick=false;
}
});
private void performTaskOnce() {
Log.i("myapp", "Performing task");
//Do something nontrivial that takes a few ms (like changing the view hierarchy)
}
In the interest of keeping DRY:
// Implementation
public abstract class OneShotClickListener implements View.OnClickListener {
private boolean hasClicked;
#Override public final void onClick(View v) {
if (!hasClicked) {
onClicked(v);
hasClicked = true;
}
}
public abstract void onClicked(View v);
}
// Usage example
public class MyActivity extends Activity {
private View myView;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myView.setOnClickListener(new OneShotClickListener() {
#Override public void onClicked(View v) {
// do clicky stuff
}
});
}
}
Bit late but this might be of use to someone. In my case I am calling another activity so;
Declare a boolean;
boolean clickable;
In the click listener;
if(clickable){
// Launch other activity
clickable = false;
}
Enable when onResume is called;
#Override
public void onResume() {
Log.e(TAG, "onResume");
super.onResume();
clickable = true;
}
You can use RxView(com.jakewharton.rxbinding2.view.RxView) is an extension around RxJava that created by Jake Wharton.
To integrate it to project you should use implementation 'com.jakewharton.rxbinding3:rxbinding:3.1.0'
Simple Java usage:
RxView.clicks(yourButton)
.sample(500, TimeUnit.MILLISECONDS)
.subscribe { action() }
In Kotlin you can create extension function to handle your clicks:
View.singleClick(action: () -> Any) {
RxView.clicks(this)
.sample(500, TimeUnit.MILLISECONDS)
.subscribe { action() }
}
Sample:
Kotlin
yourButton.singleClick({
//do some stuff here
})
Java
SingleClickListenerKt.singleClick(yourButton, () -> {
doSomeStuff();
return null;
});
Note: you can use any RxJava operators like debounce, map, first, etc if you wish.
declare a varieble
and use it as
boolean boo = false;
someButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(boo==false){
someButton.setEnabled(false);
someButton.setClickable(false);
someButton.setVisibility(View.GONE);
boo = true;
}
}
});
by this you prevent multiple clicks on your button
hope it help