I have a custom dialog with me. In which an editText id there, I am reading input through editText, putting the input to a string. This code is followed by a thread (sub) to handle one url. I want to use this string in the thread mentioned. But the thread is getting invoked before I type to the editText. How can i dynamically use the same text from the userinput inside the thread? Thanks in advance..
public void onClick(View v)
{
switch (v.getId())
{
case R.id.i1:
MyDevice.getInstance().currentUserImageId=R.drawable.jerry1;
MyDevice.getInstance().userName="You";
MyDevice.getInstance().facebook=0;
this.finish();
break;
case R.id.i2:
MyDevice.getInstance().currentUserImageId=R.drawable.chaplin1;
MyDevice.getInstance().userName="You";
MyDevice.getInstance().facebook=0;
this.finish();
break;
case R.id.i3:
MyDevice.getInstance().currentUserImageId=R.drawable.budy;
MyDevice.getInstance().userName="You";
MyDevice.getInstance().facebook=0;
this.finish();
break;
case R.id.facebook:
final Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.usernamefbdialog);
dialog.setTitle("Enter Facebook Username");
Button dialogButton = (Button) dialog.findViewById(R.id.done);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
EditText edit=(EditText)dialog.findViewById(R.id.username);
text=edit.getText().toString();
dialog.dismiss();
}
});
dialog.show();
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
try
{
MyDevice.getInstance().bitmap=getUserPic(text);
MyDevice.getInstance().facebook=1;
ImageView facebookImg=(ImageView) findViewById(R.id.facebookimg);
facebookImg.setImageBitmap(MyDevice.getInstance().bitmap);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
thread.start();
break;
}
}
Basically what you want to do is run the Thread from within the button click event, that way it runs after you get the text. See your modified code below.
The events that happen to the String occur in this order.
1. Create the String
2. Set the String equal to the edit text String
3. Start the Thread and use the String
final String theStringYouWantToUseInTheThread = null;
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
try
{
//use theStringYouWantToUseInTheThread here
MyDevice.getInstance().bitmap=getUserPic(text);
MyDevice.getInstance().facebook=1;
ImageView facebookImg=(ImageView) findViewById(R.id.facebookimg);
facebookImg.setImageBitmap(MyDevice.getInstance().bitmap);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
dialogButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
EditText edit=(EditText)dialog.findViewById(R.id.username);
theStringYouWantToUseInTheThread = edit.getText().toString();
thread.start();
dialog.dismiss();
}
});
dialog.show();
thread.start();
I'm not exactly sure if I understand but this sentence "How can i dynamically use the same text from the userinput inside the thread?"sounds like you want to implement a TextWatcher on your EditText
public class TempWatcher implements TextWatcher {
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
// you can update something here
}
}
But if you check for a valid value in your EditText when clicking the Button and only start your Thread then, it should do what you want. If this doesn't work then please clarify your problem and show where you start the Thread and how it is implemented
Related
I'm building an app that allows user to have a real time base-conversion of a number. Users input their number in an edit text, and they choose the base using plus and minus button. The problem I encountered so far is providing the real time conversion. All the editText inside the recycler view set their text to a BigInteger that can be converted depending on their base.
My idea was to update the BigInteger as the user is inputting a new number. Therefore every time users input a digit I should be able to update the BigInteger, notify the recycler view that the data as changed and then the edit text views should update automatically. Here's my ConvertViewHolder
public ConvertViewHolder(final View itemView) {
super(itemView);
mBaseTextView = (TextView) itemView.findViewById(R.id.baseLabel);
mEditText = (EditText) itemView.findViewById(R.id.numberEditText);
mMinusButton = (Button) itemView.findViewById(R.id.minusButton);
mPlusButton = (Button) itemView.findViewById(R.id.plusButton);
mRemoveButton = (ImageButton)itemView.findViewById(R.id.removeButton);
mMinusButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mRoot.get(getPosition()) > MIN_BASE) {
mRoot.set(getPosition(), (mRoot.get(getPosition()) - 1));
notifyDataSetChanged();
}
}
});
mPlusButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mRoot.get(getPosition()) < MAX_BASE){
mRoot.set(getPosition(), (mRoot.get( getPosition() ) +1));
notifyDataSetChanged();
}
}
});
mRemoveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mRoot.remove(getPosition());
notifyDataSetChanged();
}
});
mEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
if(editable.toString().length() > 0) {
// change Big Integer
mNumber.setDecimalNumber(editable.toString(), mRoot.get( getPosition() ) );
// notify change
notifyDataSetChanged();
}
}
});
// TODO: convert numbers at the same time
}
public void bindConverter(final int root){
mBaseTextView.setText(String.format("%02d", root));
// String containing all the allowed digits depending on base
String digits = mNumber.getScaleFromBase(root);
if (root < 11) {
// filter input
mEditText.setInputType(InputType.TYPE_CLASS_NUMBER |
InputType.TYPE_TEXT_FLAG_MULTI_LINE);
mEditText.setKeyListener(DigitsKeyListener.getInstance(digits));
mEditText.setSingleLine(false);
mEditText.setMaxLines(2);
} else {
mEditText.setInputType(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS |
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
mEditText.setSingleLine(false);
mEditText.setMaxLines(2);
mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_ENTER_ACTION);
// TODO: filter input for base higher than 10
}
// set editText to BigInteger displaying it in the correct base
// i.e. if the BigInteger is "8" it will be displayed as 8 if the base is 10
// and as 1000 if the base is 2
mEditText.setText(mNumber.getDecimalNumber(mRoot.get( getPosition() )));
}
}
But apparently I am not allowed to call notifySetDataHasChanged inside the TextWatcher.onTextChanged() as the compiler throws me this error:
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
which is pretty self-explanatory, but unfortunately I haven't figured out a possible workaround.
view.post(
new Runnable() {
public void run() { notifyDatasetChanged(); };
}
);
self explanatory:
call this method after RecyclerView compute a layout or scrolling (in next loop)
more explanation:
one thread = code flow synchronous
main thread = looper
looper = message que = runnable = loop
other possible solution ??
call after u exit from recycler view method
ps.
one more hint if this "piece of code" will run more then once pull the runnable in higher stack existence place (in GC scope of RecyclerView) for less usage of resources and computing time :)
private Runnable r = new Runnable {
public void run() { notifyDatasetChanged(); }
}
...
view.post(r);
...
or for generic solution pull in method using interface
public Runnable postNotify(ListAdapter la) {
return = new Runnable {
public void run() { la.notifyDatasetChanged(); }
};
}
...
private Runnable changed = postNotify(adapter);
...
view.pos(changed);
I ran into some strange UI issues while trying to display a custom content AlertDialog. The dialog asks the user to enter a name and it doesn't allow him to move forward without doing so. It is also the first thing that the user sees when the activity starts.
Sometimes, right after the application gets restarted - let's say I press the home button when the dialog is opened and then I reopen the app, the AlertDialog is being displayed as it should be but the parent activity's layout is not being loaded correctly. It actually keeps the layout from the previous Activity that the user was seeing. Even stranger, this layout is almost always displayed backwards. You can probably see that better in here. Behind the dialog it should be a blank white layout but instead there's a reverted "snapshot" of the launcher activity from the Settings app.
As the official documentation suggests I am wrapping the AlertDialog in a DialogFragment.
public class NicknamePickerDialog extends DialogFragment {
public static final String TAG = NicknamePickerDialog.class.getSimpleName();
public interface NicknameDialogListener {
void onNicknamePicked(String nickname);
void onPickerCanceled();
}
private NicknameDialogListener mListener;
private EditText mNicknameEditText;
private Button mPositiveButton;
public void setNicknameDialogListener(NicknameDialogListener listener) {
mListener = listener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Set the title
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_nickname);
// Inflate the custom content
View dialogView = getActivity().getLayoutInflater().inflate(R.layout.nickname_dialog_layout, null);
builder.setView(dialogView);
mNicknameEditText = (EditText) dialogView.findViewById(R.id.nickname);
builder.setPositiveButton(R.string.great, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (mListener != null) {
mListener.onNicknamePicked(mNicknameEditText.getText().toString());
}
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (mListener != null) {
mListener.onPickerCanceled();
}
}
});
final AlertDialog dialog = builder.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
mPositiveButton = dialog.getButton(Dialog.BUTTON_POSITIVE);
mPositiveButton.setEnabled(false);
}
});
mNicknameEditText.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) { }
#Override
public void afterTextChanged(Editable s) {
mPositiveButton.setEnabled(s.length() != 0);
}
});
return dialog;
}
}
This is the Activity code
public class ChatActivity extends Activity implements NicknamePickerDialog.NicknameDialogListener {
private String mNickname;
private TextView mWelcomeTextView;
private NicknamePickerDialog mDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_activity_layout);
mWelcomeTextView = (TextView) findViewById(R.id.welcome);
mDialog = new NicknamePickerDialog();
mDialog.setNicknameDialogListener(this);
}
private void showNicknamePickerDialog() {
mDialog.show(getFragmentManager(), NicknamePickerDialog.TAG);
}
#Override
public void onNicknamePicked(String nickname) {
mNickname = nickname;
mWelcomeTextView.setText("Welcome " + nickname + "!");
}
#Override
public void onPickerCanceled() {
if (mNickname == null) {
finish();
}
}
#Override
protected void onResume() {
super.onResume();
if (mNickname == null) {
showNicknamePickerDialog();
};
}
#Override
protected void onPause() {
super.onPause();
mDialog.dismiss();
}
}
At first I suspected that it probably happens because I am calling the DialogFragment's show method inside the activity's onCreate() callback (as it might be too soon), but postponing it to as late as onResume() does not solve the problem. This issue also occurs on orientation changes, leaving the background behind the dialog black. I am sure I am doing something wrong but I really can't find out what that is.
I am seriously not getting that what you are trying to do. but one thing you have done the wrong is that.
Do overide method OnCreateView() in class NicknamePickerDialog and do the below
// Inflate the custom content
View dialogView = getActivity().getLayoutInflater().inflate(R.layout.nickname_dialog_layout, null);
builder.setView(dialogView);
mNicknameEditText = (EditText) dialogView.findViewById(R.id.nickname);
mNicknameEditText.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) { }
#Override
public void afterTextChanged(Editable s) {
mPositiveButton.setEnabled(s.length() != 0);
}
});
return dialogView;
also your alert dialog will not work . better create buttons and title you can in onCreateDialog().
dialog.setTitle(R.string.pick_nickname);
Hope this will work.
I have around 5 edittexts.When i click submit button,it has to check whether all fields are entered or not.Along with it if any value is not entered,the focus has to go to that desired edittext.If there are many editexts empty,then the focus has to go in top down order.I have used seterror method but when i type in that editext the error msg is not going.After entering values the focus is not going to the next edittext.how to solve this issue?
caseno,dateloss,policy_rep,reg_book,Dri_lic are the different editexts used.I have written code for one editext below
caseno.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasfocus)
{
if(!hasfocus && caseno.getText().length()==0)
{
new Handler().postDelayed(new Runnable()
{
#Override
public void run() {
//ev2.clearFocus();
dateloss.clearFocus();
policy_rep.clearFocus();
reg_book.clearFocus();
Dri_lic.clearFocus();
caseno.requestFocus();
caseno.setError("Enter this field");
}
}, 100);
}
}
});
btnsubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(caseno!=null||dateloss!=null||policy_rep!=null||reg_book!=null||Dri_lic!=null)
{
Send_reportclaim_Async reportsync=new Send_reportclaim_Async();
reportsync.execute();
}
}
});
Android provides a setError() method for this:
if(edttxtDescription.getText().toString().trim().equals(""))
{
edttxtDescription.setError("Please provide description");
}
Define a method to check whether your EditTexts have valid data:
private boolean validateEditTexts()
{
boolean valid = true;
if(edttxtDescription.getText().toString().trim().equals(""))
{
edttxtDescription.setError("Please provide description");
valid = false;
}
// Similarly check all your EditTexts here and set the value of valid
......
......
return valid;
}
To validate all your EditTexts, call validateEditTexts() which will return true or false accordingly.
btnsubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(validateEditTexts()){
Send_reportclaim_Async reportsync=new Send_reportclaim_Async();
reportsync.execute();
}
}
});
Try this. This will work.
Check this:
for(EditText edit : editTextList){
if(TextUtils.isEmpty(edit.getText()){
// EditText is empty
}
}
Maintain array of EditText references: Like
EditText[] allEts = { caseno, dateloss, policy_rep, reg_book, Dri_lic };
Write the below code in onClick of submit button:
for (EditText editText : allEts) {
String text = editText.getText().toString();
if (text.length() == 0) {
editText.setError("enter this field");
editText.requestFocus();
break;
}
}
And, implement addTextChangedListener for all edittexts to clear the error after entering the text.
caseno.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
Editable text = caseno.getText();
if (caseno.getError() != null && text != null
&& text.length() > 0) {
caseno.setError(null);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
Use this on your button click
if(!textView1.toString().isEmpty() && !textView2.toString().isEmpty() && ...)
{
............
}
1) create this method
public static boolean isNullOrEmpty(String input) {
return input == null || input.isEmpty();
}
2) send data to it for validation
boolean answer = isNullOrEmpty(editText.gettext().toString());
btnsubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(TextUtils.isEmpty(caseno.getText().toString()))
{
caseno.requestFocus();
Toast.makeText(getApplicationContext(),"Enter the required fields", Toast.LENGTH_LONG).show();
return;
}
if(TextUtils.isEmpty(dateloss.getText().toString()))
{
dateloss.requestFocus();
Toast.makeText(getApplicationContext(),"Enter the required fields", Toast.LENGTH_LONG).show();
return;
}
}
Currently this setup is working for me...Thnks those who answered
I have a Fragment. When the Fragment is created I want to show a Progress Dialog for 3 seconds, then dismiss it and show a pop up dialog. I attach below my code.
From the onCreate() of my Fragment:
final ProgressDialog myPd_ring=ProgressDialog.show(context, "Please wait", "text..", true);
myPd_ring.setCancelable(false);
new Thread(new Runnable() {
#Override
public void run() {
try
{
Thread.sleep(3000);
} catch(Exception e)
{
}
myPd_ring.dismiss();
}
}).start();
showPopup(0, 8, 1, "Next photo");
And my popup method:
public void showPopup(final int type, int photoNo, int currPhoto, String message) {
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.popup_erroare);
dialog.setCancelable(false);
TextView textHeader;
TextView textContent;
textHeader = (TextView) dialog.findViewById(R.id.text_titlu);
textContent = (TextView) dialog.findViewById(R.id.text_error);
textHeader.setText("Procedura fotografiere");
textContent.setText("Poza nr. " + currPhoto+ " of" + noPhoto+
". " + message);
if (type == 0) {
}
Button btn_nu = (Button) dialog.findViewById(R.id.button_nu);
if (type == 0) {
btn_nu.setText("NU");
}
btn_nu.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
btn_nu.setVisibility(View.GONE);
Button btn_da = (Button) dialog.findViewById(R.id.button_da);
btn_da.setText("Fotografiere");
btn_da.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (type == 0) {
captureImage();
}
dialog.dismiss();
}
});
dialog.show();
}
The problem is that my ProgressDialog doesn't appear, the popup appears directly. If I put my pop up invoking method in the new Thread() body I get an error. It seems that you can invoke a dialog from a Runnable.
you can use the below code:
final ProgressDialog myPd_ring=ProgressDialog.show(context, "Please wait",
"text..", true);
myPd_ring.setCancelable(false);
myPd_ring.show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
myPd_ring.dismiss();
showPopup(0, 8, 1, "Next photo");
}
}, 3000);
If you have any query please let me know.
Never use sleep() in final APP.
try this way, new a Runnable(), and call postDelay(runnable, delayTimes) on a Handle.
Android Handler has a handy method postDelay() that does what you need, for example:
final ProgressDialog myPd_ring=ProgressDialog.show(context, "Please wait", "text..", true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
myPd_ring.dismiss();
// show popup
}
}, 3000);
In Android, all View related tasks must be executed in the main thread, doing it in other threads will result in error. If you want to do in inside a background task for example, you'll need to use myactivity.runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
// show my popup
}
});
I have some problem. Dialog.dismiss() does not work.
I want to input ip, username, password to login WinServer 2003. When I clicked Submit button, the dialog can't be closed. To be noted, my Thread-socket able to retrieve messages from Server and send messages back to Server. The Dialog can only be closed When the Thread-socket got error.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.jiemian);
netInit();
JieMianActivity.jiemian = this;
LayoutInflater factory = LayoutInflater.from(JieMianActivity.this);
View view = factory.inflate(R.layout.login, null);
dialog02 = new AlertDialog.Builder(JieMianActivity.this)
.setIcon(android.R.drawable.btn_star)
.setTitle("login")
.setView(view)
.setPositiveButton("submit", onclickButton)
.setNegativeButton("cancel", onclickButton).create();
dialog02.show();
}
private OnClickListener onclickButton = new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Log.v("which", which+"");
switch(which){
case Dialog.BUTTON_POSITIVE:
dialog.dismiss();//doesn't work , cann't close dialog.
EditText ip = (EditText) findViewById(R.id.ip);
EditText username = (EditText) findViewById(R.id.username);
EditText password = (EditText) findViewById(R.id.password);
new Connect(JieMianActivity.jiemian).run();//do some socket thing
break;
case Dialog.BUTTON_NEGATIVE:
dialog.dismiss();
JieMianActivity.jiemian.finish();
break;
}
}
};
This is my Thread:
class Connect extends Thread{
private JieMianActivity jiemain;
public Connect(JieMianActivity jiemian){
this.jiemain = jiemian;
}
public void run(){
//Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
try {
Display display = getWindowManager().getDefaultDisplay();
InputStream is = getResources().getAssets().open(
connect2RDP.mapFile);
sfv = (SurfaceView) findViewById(R.id.surfaceView);
sfh = sfv.getHolder();
sfh.addCallback(JieMianActivity.jiemian);
if (conn.connect("192.168.10.134", "Adminstrator", "123",
display.getWidth(), display.getHeight(), 3389, is)) {
Log.v("login", "success");
//dialog02.dismiss();
Log.v("login", "ok");
canvas = new MyCanvas();
canvas.setRop(new RasterOp());
canvas.setHeight(Options.height);
canvas.setWidth(Options.width);
canvas.setRight(Options.width - 1);
canvas.setBottom(Options.height - 1);
canvas.setBackstore(new WrappedImage(Options.width,
Options.height, JieMianActivity.jiemian));
canvas.setJiemian(JieMianActivity.jiemian);
canvas.setSurView(sfv);
canvas.setSurHolder(sfh);
conn.doconnect(JieMianActivity.jiemian);// 启动RDP
// init();
}
} catch (OrderException e) {
} catch (Exception e) {
}
}
};
You need to change your code to start a Thread, You need to call the method start() - that will execute the run() method written in that Thread.
So,
Invoke Connect.start() instead of Connect.run() inside your onClick handler.
I think you should close your alert dialog in UI thread else it wont work. You can do this in two ways : 1. Use message handler 2. Use RunOnUiThread. Sample for your reference :
1.
messageHandler.sendEmptyMessageDelayed(unique_id, 500);
private Handler messageHandler = new Handler()
{
#Override
public void handleMessage(Message msg) {
switch(msg.what) {
case unique_id:
// do here
break;
}
}
};
2.
Runnable hide_ui = new Runnable() {
#Override
public void run() {
// do here
}
};
runOnUiThread(hide_ui);