Continuous Message as long as EditText is being used - java

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.

Related

How to take checked radio buttons on a user input form in Android and store the selections as a String

I have a very simple Android application (using Java) that will take user input. It has several input fields with EditTexts and Radiobuttons and a submit Button. I am not sure if I am implementing the Radiobuttons correctly.
The app compiles and runs okay, when the activity opens I can input values etc. but nothing happens when selecting the Submit button. I have tried debugging but as the app does not crash it has hard to know what is the issue.
N.B. my API, PHP scripts and database etc is working; I have working sign up / sign in activities and the POST method for my user input form is working as I have tested with Postman
public class IncidentActivity extends AppCompatActivity {
private EditText editTextStreet, editTextTown, editTextDetails;
private RadioButton btnGenUnknown, btnGenMale, btnGenFemale, btnBedUnknown, btnBedYes, btnBedNo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_incident);
editTextStreet = findViewById(R.id.editTextStreet);
editTextTown = findViewById(R.id.editTextTown);
btnGenUnknown = findViewById(R.id.btnGenUnknown);
btnGenMale = findViewById(R.id.btnGenMale);
btnGenFemale = findViewById(R.id.btnGenFemale);
btnBedUnknown = findViewById(R.id.btnBedUnknown);
btnBedYes = findViewById(R.id.btnBedYes);
btnBedNo = findViewById(R.id.btnBedNo);
editTextDetails = findViewById(R.id.editTextDetails);
Button button = findViewById(R.id.buttonSubmit);
button.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
logIncident();
}
});
}
private void logIncident() {
String street = editTextStreet.getText().toString().trim();
String town = editTextTown.getText().toString().trim();
String details = editTextDetails.getText().toString().trim();
String gender;
String bedded;
if (!btnGenUnknown.isChecked()) {
if (!btnGenMale.isChecked()){
btnGenFemale.setText("Female");
gender = btnGenFemale.toString();
}
else{
btnGenMale.setText("Male");
gender = btnGenMale.toString();
}
}else{
btnGenUnknown.setText("Unknown");
gender = btnGenUnknown.toString();
}
if (!btnBedUnknown.isChecked()) {
if (!btnBedYes.isChecked()){
btnBedNo.setText("No");
bedded = btnBedNo.toString();
}
else{
btnBedYes.setText("Yes");
bedded = btnBedYes.toString();
}
}else{
btnBedUnknown.setText("Unknown");
bedded = btnBedUnknown.toString();
}
/* Logging incident using the API call */
Call<DefaultResponse> call = RetrofitClient
.getInstance()
.getApi()
.logIncident(street, town, gender, bedded, details);
/* Executing the HTTP call */
call.enqueue(new Callback<DefaultResponse>() {
#Override
public void onResponse(Call<DefaultResponse> call, Response<DefaultResponse> response) {
if(response.code() == 201){
DefaultResponse dr = response.body();
Toast.makeText(IncidentActivity.this, dr.getMsg(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<DefaultResponse> call, Throwable t) {
Toast.makeText(IncidentActivity.this, "Something is wrong", Toast.LENGTH_LONG).show();
}
});
}
}
On hitting the submit button the values should be stored as Strings and posted to my database
Activity layout
//Create an object for button
Button button = findViewById(R.id.submit_button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Call your method from here
logIncident();
}
});

switch between different listener

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

how to check whether Button is clicked or not

I have to check whether the button is clicked or not.if clicked application has to do one task and if not, application has to do another task. I tried to do this, but I am getting no connection error which I have put at the end of the code in catch block.
protected void onCreate(Bundle savedInstanceState) {
PracticeVO practiceObj;
try {
setTitle("Klarity");
setPrefBtn = (Button) findViewById(R.id.setPrefBtn);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_klarity_home);
/*
* asynchronous calls
*/
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
final ConnectionHelper con = new ConnectionHelper();
/*
* It will connect to DB and fetches the Practice Information
*/
if (Btnclicked == false) {
String allPracticesStr = null;
here I have set the boolean variable 'Btnclicked' true.
setPrefBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Btnclicked=true;
Intent setPrefIntent = new Intent(KlarityHome.this,
SetPreferences.class);
startActivity(setPrefIntent);
}
});
But After executing this The cursor is directly goin here and displaying 'no connection'.
catch (Exception ex) {
Context context = getApplicationContext();
CharSequence text = "There is some error in application";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
System.out.println("no connection");
}
}
Anyone has solution on this.
as you said
"the button is clicked or not.if clicked application has to do one task and if noapplication has to do another task"
so, if i were you, i'll put 2 radio buttons, every one with the text of the task you want to do, and add a listener for them, like this:
radiobutton1.setOnCheckedChangeListener(new RadioButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
radiobutton2.setChecked(false);
}
});
radiobutton2.setOnCheckedChangeListener(new RadioButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
radiobutton1.setChecked(false);
}
});
and last, in the button do the task you want to do:
Button.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if(radiobutton1.isChecked){
//do task 1
}else{
//do task2}
}
});
You are getting an NPE(NullPointerException) since you havent initialised Btnclicked in your code at the time of usage.ie you are checking whether Btnclicked is false like
if (Btnclicked == false) {
But at the time of this checking, the value of Btnclicked is null and hence an NPE.
So to get rid of this, you just add either
Btnclicked=true;
or
Btnclicked=false;
before the if loop according to your logic.
OR
or just replace the declaration from Boolean Btnclicked; to Boolean Btnclicked=false;
Hope this helps.
Remove Btnclicked you don't need that. OnClickListner is meant for what you're trying to do. The code which you want to run when button is not pressed put it before
//When button is not pressed
setPrefBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//When button is pressed
}
});
And the code which you want to run when the button is clicked place it inside the onClick(){}

Android Setting Up Splash Screen(Activity) Like Iphone Part1

I have three images with me and i want them to appear on first layout xml like a splash view so that they can be viewed only once i.e that activity will be called only once when app get's installed or if app get's a new update otherwise app should always start from the Second activity, i don't know how should i begin with this :
Can any one tell me any idea how this can be done.
To show splash for only once.
Next part of this question is here
Coding will be much appreciated.
Save a flag in the Preferences when you start up the application, after you've done the welcome screen stuff. Check for this flag before you show the welcome screen. If the flag is present (in other words, if it's not the first time), don't show it.
In your activity:
SharedPreferences mPrefs;
final String welcomeScreenShownPref = "welcomeScreenShown";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
// second argument is the default to use if the preference can't be found
Boolean welcomeScreenShown = mPrefs.getBoolean(welcomeScreenShownPref, false);
if (!welcomeScreenShown) {
// here you can launch another activity if you like
// the code below will display a popup
String whatsNewTitle = getResources().getString(R.string.whatsNewTitle);
String whatsNewText = getResources().getString(R.string.whatsNewText);
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(whatsNewTitle).setMessage(whatsNewText).setPositiveButton(
R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
SharedPreferences.Editor editor = mPrefs.edit();
editor.putBoolean(welcomeScreenShownPref, true);
editor.commit(); // Very important to save the preference
}
}
Try this :
public class MainActivity extends Activity {
private Thread mSplashThread;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
final MainActivity sPlashScreen = this;
mSplashThread = new Thread() {
#Override
public void run() {
try {
synchronized (this) {
wait(4000);
}
} catch (InterruptedException ex) {
}
finish();
Intent intent = new Intent();
intent.setClass(sPlashScreen, StartNewActivity.class);// <-- Activity you want to start after Splash
startActivity(intent);
}
};
mSplashThread.start();
} catch (Exception e) {
}
}
#Override
public boolean onTouchEvent(MotionEvent evt) {
try {
if (evt.getAction() == MotionEvent.ACTION_DOWN) {
synchronized (mSplashThread) {
mSplashThread.notifyAll();
}
}
} catch (Exception e) {
}
return true;
}
}
you put an Image in splash.xml to show
to do this you have to detect the first launch of your application. To do so you can store a boolean value as #Nirav suggested.
And for the splash screen, You can consider using Fragments and ViewPager to create an activity which will only be shown for the first time

Avoid multi-click in image view android

I try to use this code to prevent multi-click in ImageView but it doesn't help.
Boolean isClicked = false;
#Override
public void onClick(View v)
{
if (v == imgClick && !isClicked)
{
//lock the image
isClicked = true;
Log.d(TAG, "button click");
try
{
//I try to do some thing and then release the image view
Thread.sleep(2000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
isClicked = false;
}
}
In the log cat, I can see 5 lines "button click" when I click on ImageView for 5 times as quickly as possible. I can see the log cat print the first line, wait for a while (2 seconds) and then print the next line. I think when I click the ImageView, the fired event is moved to queue in order, isn't it?. So how can I stop that?
I also try to use setEnable() or setClickable() instead of isClicked variable but it doesn't work too.
Just try this working code
Boolean canClick = true; //make global variable
Handler myHandler = new Handler();
#Override
public void onClick(View v)
{
if (canClick)
{
canClick= false; //lock the image
myHandler.postDelayed(mMyRunnable, 2000);
//perform your action here
}
}
/* give some delay..*/
private Runnable mMyRunnable = new Runnable()
{
#Override
public void run()
{
canClick = true;
myHandler.removeMessages(0);
}
};
Instead of sleeping in 2 seconds, I use some task like doSomeThing() method (has accessed UI thread), and I don't know when it completed. So how can I try your way?
//I referred this android link. You can handle thread more efficiently but i hope below code will work for you..
//you try this and
Boolean canClick = true; //make global variable
public void onClick(View v) {
if(canClick){
new DownloadImageTask().execute();
}
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... urls) {
Log.d("MSG","Clicked");
canClick =false;
//perform your long operation here
return null;
}
protected void onPostExecute(Bitmap result) {
canClick =true;
}
}
You could keep track of the last consumed click upon your View, and based on it either perform the necessary actions, or simply return:
private long calcTime;
private boolean isClickedLately(final long millisToWait)
{
if (System.currentTimeMillis() - calcTime < millisToWait)
return true;
return false;
}
#Override
public void onClick(View v)
{
if (isClickedLately(2000))
return;
calcTime = System.currentTimeMillis();
Log.d(TAG, "consuming button click");
// perform the necessary actions
}
With the millisToWait parameter you can adjust the threshold of "waiting", but if you know that you want to wait exactly 2 seconds between two consecutive clicks, you can eliminate it.
This way you don't have to deal with Threads, which is good, since it's not a great idea to make the gui thread wait.

Categories