I want: if user already put name and choose game types, user can click button 'OK' but if user doesn't already put name and choose game types, user can't click button 'OK'.
public class UserConfig extends Activity {
Button userConfigBack;
Button userConfigOK;
EditText userNameTextbox;
Spinner gameTypes;
private String gameType;
private String playerName;
private Handler handler;
Thread validation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_config);
userConfigBack = (Button) findViewById(R.id.user_config_back);
userConfigOK = (Button) findViewById(R.id.user_config_ok);
userNameTextbox = (EditText) findViewById(R.id.user_name_textbox);
gameTypes = (Spinner) findViewById(R.id.game_types);
gameTimes = (Spinner) findViewById(R.id.game_times);
userConfigOK.setEnabled(false);
userConfigOK.setClickable(false);
setName();
setGameType();
handler = new Handler();
autoValidation();
OK();
}
public void setName() {
playerName = userNameTextbox.getText().toString();
userNameTextbox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
playerName = userNameTextbox.getText().toString();
nameLabel.setText(playerName);
}
#Override
public void afterTextChanged(Editable arg0) {
}
});
}
public void setGameType() {
gameTypes.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View arg1,
int arg2, long arg3) {
gameType = (String) gameTypes.getSelectedItem();
gameTypeLabel.setText(gameType);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
public void OK() {
userConfigOK.setOnClickListener( new OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(UserConfig.this, EnemyConfig1.class);
startActivity(intent);
}
});
}
public void autoValidation() {
validation = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
if(!gameType.equals("")) {
if(!playerName.equals("")) {
userConfigOK.setEnabled(true);
userConfigOK.setClickable(true);
}
}
}
});
}
});
validation.start();
}
}
I create thread inside method AUTOVALIDATION. If editText not null and user already choose game types spinner, user can click button OK. But
userConfigOK.setEnabled(true);
userConfigOK.setClickable(true);
doesn't work.
You can't change any UI elements from another Thread. Try to use a runOnUiThread this should solve the problem.
You really should read this carefully: http://developer.android.com/guide/components/processes-and-threads.html This will save you al lot of time if you are working with Threads.
And here is an example that helped me a lot:
how to use runOnUiThread
add a text watcher to your edittext and then use this if elsestatement:
if(!userNameTextbox.getText().toString().equals("")){
//do your job
}else{
//Toast some thing
}
Related
I am trying to disable my button if my input edit texts are empty. I am using text watcher for this. To test it out , i have only tried with only two edit texts to start.
However, my button stays enabled no matter what.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_profile);
fnameInput = findViewById(R.id.et_firstname);
lnameInput = findViewById(R.id.et_lastname);
numberInput = findViewById(R.id.et_phone);
emailInput = findViewById(R.id.et_email);
nextBtn = findViewById(R.id.btn_next);
fnameInput.addTextChangedListener(loginTextWatcher);
lnameInput.addTextChangedListener(loginTextWatcher);
nextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
launchNextActivity();
}
});
}
Text watcher method
private TextWatcher loginTextWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String firstNameInput =firstNameInput.getText().toString().trim();
String lastNameInput = lastNameInput.getText().toString().trim();
// tried doing it this way
nextBtn.setEnabled(!firstNameInput.isEmpty() && !lastNameInput.isEmpty());
//What i've also tried
if(firstNameInput.length()> 0 &&
lastNameInput.length()>0){
nextBtn.setEnabled(true);
} else{
nextBtn.setEnabled(false);
}
}
#Override
public void afterTextChanged(Editable s) {
}
};
I expect the button to be disabled if one or all inputs are empty and enabled when all input fields are filled out.
create a method check all condition there like
private void checkTheConditions(){
if(condition1 && condition2)
nextBtn.setEnabled(true)
else
nextBtn.setEnabled(false)
}
call this method from afterTextChanged(Editable s) method
Let us consider this case for 2 EditTexts only as for now.
define 2 global CharSequence as below
CharSequence fName="";
CharSequence lName="";
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_profile);
fnameInput = findViewById(R.id.et_firstname);
lnameInput = findViewById(R.id.et_lastname);
numberInput = findViewById(R.id.et_phone);
emailInput = findViewById(R.id.et_email);
nextBtn = findViewById(R.id.btn_next);
fnameInput.addTextChangedListener(textWatcher);
lnameInput.addTextChangedListener(textWatcher2);
nextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
launchNextActivity();
}
});
}
then you have to define different textwatcher for each of your Edittext
then inside each of these textWatcher assign values to CharSequence defined above
private TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
fName=s;
validate(); //method to enable or disable button (find method below)
}
#Override
public void afterTextChanged(Editable s) {
}
};
now textWatcher2
private TextWatcher textWatcher2 = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
lName=s;
validate(); //method to enable or disable button (find method below)
}
#Override
public void afterTextChanged(Editable s) {
}
};
now write validate method
void validate(){
if (fName.length()>0 && lName.length()>0){
nextBtn.setEnabled(true);
}else {
nextBtn.setEnabled(false);
}
}
Oh! You did a small mistake. Use OR condition instead of AND. So your code should be
nextBtn.setEnabled(!firstNameInput.isEmpty() || !lastNameInput.isEmpty());
And TextWatcher will only notify when you will manually change the inputs of EditText. So TextWatcher will not wark at starting. So at first in onCreate method you should manually check those EditText feilds.
Edit:
Android new DataBinding library is best suitable for this purpose.
I want to reduce request to Google Places API by adding delay for every user input but i am not sure how to implement this. This is what i usually do to add delay to my EditText waiting for user's input:
editTextEmail.addTextChangedListener(new TextWatcher() {
final Handler handler = new Handler();
Runnable runnable;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
isEmailValid = false;
textInputLayoutEmail.setError(null);
enableDisableButton();
handler.removeCallbacks(runnable);
}
#Override
public void afterTextChanged(Editable s) {
runnable = new Runnable() {
#Override
public void run() {
callGooglePlacesAPI()
}
};
handler.postDelayed(runnable, 1000);
}
});
This is my code to call Google PLaces API:
editTextLocation.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
editTextLocation.setShowSoftInputOnFocus(false);
searchLocation();
}
}
});
public void searchLocation(){
try
{
editTextLocation.clearFocus();
//hide soft keyboard
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_OVERLAY)
.build(getActivity());
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
}catch (Exception e){
e.printStackTrace();
}
}
Is there a way to do this? Please help give advice on this. Thank you.
I have a custom ActivityIndicator defined as this
public class ActivityIndicator extends Dialog
{
private ImageView progress;
private ImageView bottomProgress;
private int type = INDICATOR_SIMPLE;
public static final int INDICATOR_SIMPLE = 0;
public static final int INDICATOR_BOTTOM = 1;
public ActivityIndicator(Context context, int theme, int type)
{
super(context, theme);
this.type = type;
onCreate(null);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_indicator);
progress = (ImageView) findViewById(R.id.progress);
bottomProgress = (ImageView) findViewById(R.id.bottomProgress);
if(type == INDICATOR_BOTTOM)
{
progress.setVisibility(View.INVISIBLE);
}
else if(type == INDICATOR_SIMPLE)
{
bottomProgress.setVisibility(View.INVISIBLE);
}
this.setCancelable(false);
}
#Override
public void show()
{
progress.clearAnimation();
bottomProgress.clearAnimation();
if(type == INDICATOR_BOTTOM)
{
progress.setVisibility(View.INVISIBLE);
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.rotating_img);
bottomProgress.startAnimation(anim);
}
},400);
}
if(type == INDICATOR_SIMPLE)
{
bottomProgress.setVisibility(View.INVISIBLE);
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
Animation anim = AnimationUtils.loadAnimation(getContext(), R.anim.rotating_img);
progress.startAnimation(anim);
}
},400);
}
super.show();
}
#Override
public void dismiss()
{
super.dismiss();
progress.clearAnimation();
bottomProgress.clearAnimation();
}
}
In my activity I initialize it as:
indicator = new ActivityIndicator(this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen, ActivityIndicator.INDICATOR_SIMPLE);
Now as seen in code , default style cancelable is false.
However at some point i do want to put it cancelable , here is my code:
indicator.setCancelable(true);
indicator.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
finish();
}
});
indicator.show();
When I try to press the back button, nothing happens, the dialog doesn't cancel nor the cancel listener. What is wrong here? Why is it not cancelling automatically on back key pressed
Don't Override onCreate(). That onCreate(null) method that you invoke is what's screwing up your code. Rather use an initializer pattern to initialize the Dialog.
If you change your onCreate to an initialize() and invoke that from the constructor the code will work.
Look at the following.
public ActivityIndicator(Context context, int theme, int type)
{
super(context, theme);
this.type = type;
initialize();
}
protected void initialize()
{
setContentView(R.layout.dialog_indicator);
setCancelable(false);
progress = (ImageView) findViewById(R.id.progress);
bottomProgress = (ImageView) findViewById(R.id.bottomProgress);
if(type == INDICATOR_BOTTOM)
{
progress.setVisibility(View.INVISIBLE);
}
else if(type == INDICATOR_SIMPLE)
{
bottomProgress.setVisibility(View.INVISIBLE);
}
}
Please comment your seton cancellabel and use below code and check.
indicator.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
finish();
}
}
}
When you are creating an instance of ActivityIndicator, in the OnCreate method, setCancelable is set to false.
Try removing that..
Got you problem just change your constructor like below and you would get your cancel listner called:
public ActivityIndicator(Context context, int theme, int type, boolean isCancelable)
{
super(context, theme);
this.type = type;
onCreate(null);
this.setCancelable(isCancelable); //setcancelable here on the basis of boolean value and remove setcancelable from onCreate()
}
Call the constructor with one more argument which is boolean true/false
Note: Don't forget to remove setCancelable() from onCreate() method.
READ THIS : I want to like this.... if user have input name and choose game types. user can click 'OK' button. if user haven't input name and choose game types he can't click 'OK' button.
I create thread to solve this problem...
But when I run this app. I can't go to this UI again..
Something wrong in method 'autoValidation'
And code userConfigOK.setClickable(false); doesn't work. I don't know why..
btw, android is hard. . . .
This is the source code :
public class UserConfig extends Activity {
private String gameType;
private String gameTime;
private String playerName;
private int IDChar = 0;
Thread validation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_config);
userConfigOK.setClickable(false);
inputName();
chooseCharacter();
setGameType();
back();
autoValidation();
OK();
}
public void inputName() {
playerName = userNameTextbox.getText().toString();
}
public void setGameType() {
gameTypes.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View arg1,
int arg2, long arg3) {
gameType = (String) gameTypes.getSelectedItem();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
}
public void OK() {
userConfigOK.setOnClickListener( new OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(UserConfig.this, EnemyConfig1.class);
startActivity(intent);
validation.stop();
}
});
}
public void autoValidation() {
validation = new Thread(new Runnable() {
#Override
public void run() {
if( ( !gameType.trim().equals("") ) && ( !playerName.trim().equals("") ) )
{
userConfigOK.setClickable(true);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
validation.start();
}
}
Try this
userConfigOK.setEnabled(false);
Instead of
userConfigOK.setClickable(false);
You could just have the onClickListener check to see if there is any text entered, and if there is an item selected from the grid. If the user hasn't selected anything, you could make a Toast that prompts the user to enter the values required.
I am creating a sound board and after clicking about 30 different sounds it stops working; I believe android is running out of memory. Below is my code. How can I implement .release() so that when the sound is done playing it is released? I don't really care if two things play at the same time; the clips are t0o short for this to be possible. I would just like to get my code set.
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.start();
}
});
I have done a lot of searching around but due to my lack of java/android knowledge I have not been able to get anything to work. Thanks in advance, let me know if anyone needs anymore code.
I left a comment, but I'll post an answer to show what I mean anyway...
The idea is that you have a set number of MediaPlayer instances that you can use. That way you never exceed the maximum number of instances. The array should be the length of the number of concurrent sounds you expect to be able to hear. If the sounds are local files, the length of time it takes to prepare the sounds should be almost negligible, so calling create inside the click handler should not result in terrible performance. Each of your buttons is associated with a particular resource, I suppose, so I set up a helper method to create and play the sounds for each button in the same way.
public class soundPageOne extends Activity {
private MediaPlayer[] mPlayers = new MediaPlayer[2];
private int mNextPlayer = 0;
#Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
Button playSound1 = (Button)this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startSound(R.raw.peter1);
}
});
}
public void onDestroy() {
super.onDestroy(); // <---------------------- This needed to be there
for (int i = 0; i < mPlayers.length; ++i)
if (mPlayers[i] != null)
try {
mPlayers[i].release();
mPlayers[i] = null;
}
catch (Exception ex) {
// handle...
}
}
private void startSound(int id) {
try {
if (mPlayers[mNextPlayer] != null) {
mPlayers[mNextPlayer].release();
mPlayers[mNextPlayer] = null;
}
mPlayers[mNextPlayer] = MediaPlayer.create(this, id);
mPlayers[mNextPlayer].start();
}
catch (Exception ex) {
// handle
}
finally {
++mNextPlayer;
mNextPlayer %= mPlayers.length;
}
}
}
Create a class, say AudioPlayer with a SoundPool variable. Setup a constructor to initialise the AudioPlayer object and create a Play method. SoundPool works better for short sounds played many times and does not require you to release.
public class AudioPlayer {
private SoundPool sPool = new SoundPool(Integer.MAX_VALUE, AudioManager.STREAM_MUSIC, 0);
public AudioPlayer(Context c, int id){
sounds.put("1",sPool.load(c, id, 1));
}
public void play(Context c) {
sPool.play("1", 1, 1, 1, 0, 1f);
}
}
So your class should look like
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final AudioPlayer ap = new AudioPlayer(this, R.raw.sound);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ap.play();
}
});
Could you use a MediaPlayer.OnCompletionListener?
Something like:
public class soundPageOne extends Activity implements MediaPlayer.OnCompletionListener {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final MediaPlayer pg1 = MediaPlayer.create(this, R.raw.peter1);
//***set the listener here***
pg1.setOnCompletionListener(this);
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.start();
}
});
}
//***this code will be executed once the sound finishes playing***
#Override
public void onCompletion(MediaPlayer mp) {
//log messages, other things can go here
mp.release();
}
Try something like this
Your activity class:
public class soundPageOne extends Activity {
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.soundsone);
final AudioPlayer pg1 = new AudioPlayer();
Button playSound1 = (Button) this.findViewById(R.id.peter1Button);
playSound1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pg1.play(this, R.raw.sound);
}
});
}
This is another Java Class:
public class AudioPlayer {
private MediaPlayer mPlayer;
public void stop() {
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
}
public void play(Context c, int sound) {
stop();
mPlayer = MediaPlayer.create(c, sound);
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
stop();
}
});
mPlayer.start();
}
public boolean isPlaying() {
return mPlayer != null;
}
}