Today I'm developing an App which can intercept the launch between activities, My key code is:
ActivityManagerNative.getDefault().setActivityController(new InterceptActivityController(), false);
private class InterceptActivityController extends IWeChatActivityController.Stub {
void InterceptActivityController() {}
#Override
public boolean activityStarting(Intent intent, String pkg) {
showDialog();
return false;
}
}
private void showBottomDialog() {
Log.d(TAG, "showBottomDialog");
Dialog bottomDialog = new Dialog(mContext);
View contentView = LayoutInflater.from(this).inflate(android.R.layout.simple_list_item_2, null);
bottomDialog.setContentView(contentView);
ViewGroup.LayoutParams layoutParams = contentView.getLayoutParams();
layoutParams.width = getResources().getDisplayMetrics().widthPixels;
contentView.setLayoutParams(layoutParams);
bottomDialog.getWindow().setGravity(Gravity.BOTTOM);
bottomDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
bottomDialog.show();
}
I defined a Button and planned to start an Activity after clicking it. But now I intercept this action and just show a dialog in the function of activityStarting and then return false, after dismissing this dialog, I click the button again, but nothing works, dialog doesn't show any more, Who knows the reason ? Maybe I think this is a google source bug, but I'm not sure.
You know the Dialogs need to be Shown in a Timely manner. I mean You need the Dialog to be Shown for How Long? When you Start showing a Dialog and Dismiss it, It's Not Destroyed, It's just Dismissed.
Look at the Code below. I wrote this in my own app, It's Safe. Try it and see if you're satisfied with it:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bottomDialog.show();
new Thread(new Runnable() {
#Override
public void run() {
try {
for (int i = 0; i <= 1200; i++) {
Thread.sleep(100); //The time it takes to update i
if (i = 1200) {
bottomDialog.dismiss();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
You can use AsyncTask as well. Also, I put the whole thing in a Click Listener just to show how it can be used.
The idea is define a showing Time for the Dialog
Related
I have a button that when click shows a dialog. But when you click the button quickly in multiple times, it will show 2 or more dialog on the screen. Depends on how many times you click the button before dialog shows. So I have to close each dialog many times...
I already used dialog.isShowing but it seems that it will ignore it when you click the button quickly in multiple times.
...So I want to click button at a time when dialog is closed.
private var mFlag = false
fun myButton(view : View) {
var tempDialog = AlertDialog.Builder(this).create()
if (!mFlag) {
myDialog.show()
mFlag = true
}
if(dialog.isShowing){
mFlag = false
}
}
I have made public method for avoid double clicking issue on view.
Please check this method,
/***
* To prevent from double clicking the row item and so prevents overlapping fragment.
* **/
public static void avoidDoubleClicks(final View view) {
final long DELAY_IN_MS = 900;
if (!view.isClickable()) {
return;
}
view.setClickable(false);
view.postDelayed(new Runnable() {
#Override
public void run() {
view.setClickable(true);
}
}, DELAY_IN_MS);
}
You can use the method by following way,
buttonTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(String clickedText) {
Utils.avoidDoubleClicks(alertViewHolder.tv_alert);
// Rest code here for onlick listener
});
Or another way is,
private long lastClickTime = 0;
View.OnClickListener buttonHandler = new View.OnClickListener() {
public void onClick(View v) {
// preventing double, using threshold of 1000 ms
if (SystemClock.elapsedRealtime() - lastClickTime < 1000){
return;
}
lastClickTime = SystemClock.elapsedRealtime();
}
}
I am new in android, I want see my message in a Toast but it shows to for a little time.
I want to show the message for example until one hour or more.
No you can't. Use a Custom Dialog and dismiss it when you want. But i wonder why do you want to display some kind of pop up for such a long time.
I would suggest re-considering your design.
You may also want to check Crouton
https://github.com/keyboardsurfer/Crouton
Try to use Dialog box instead of toast
SingleButtton.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// Creating alert Dialog with one Button
AlertDialog alertDialog = new AlertDialog.Builder(AlertDialogActivity.this).create();
// Setting Dialog Title
alertDialog.setTitle("Alert Dialog");
// Setting Dialog Message
alertDialog.setMessage("Welcome to Android Application");
// Setting Icon to Dialog
alertDialog.setIcon(R.drawable.tick);
// Setting OK Button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which)
{
// Write your code here to execute after dialog closed
}
});
// Showing Alert Message
alertDialog.show();
}
});
The values of LENGTH_SHORT and LENGTH_LONG are 0 and 1.they are treated as flags therefore I think it is not possible to set time other than this.
You can try this :
Edit:
int time = 1000*60 // 1 hour
for (int i=0; i < time; i++)
{
Toast.makeText(this, "Your msg", Toast.LENGTH_LONG).show();
}
Well, like said here, there is no proper way to do this.
But, there is a sort of hack to it - just run your Toast in a for-loop, and the amount of iterations will control the length. For example - running the loop twice (like below) will double the time. Running it 3 times will triple the length. Again, it is just a work-around that works :-)
for (int i=0; i < 2; i++)
{
Toast.makeText(this, "test", Toast.LENGTH_LONG).show();
}
You must take into account that it does have flaws - it the user quits the app before the end of loop it will continue to show, and, on some devices the Toast might flicker between each iteration. So, up to you!
The purpose of toast is showing a simple message in a time. You can't show it for long time. you can customized your own UI for Toast messages using dialog.
public static void showCustomToast(final Activity mActivity,final String helpText,final int sec) {
if(mActivity != null){
mActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
int mSec = 3000;
if(sec != 0){
mSec = sec;
}
LayoutInflater inflater = mActivity.getLayoutInflater();
View messageDialog = inflater.inflate(R.layout.overlay_message, null);
layer = new CustomLayout(mActivity);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
messageDialog.setLayoutParams(params);
TextView message = (TextView) messageDialog.findViewById(R.id.messageView);
Button okBtn = (Button) messageDialog.findViewById(R.id.messageOkbtn);
if(okBtn != null){
okBtn.setVisibility(View.GONE);
}
message.setText(helpText);
final Dialog dialog = new Dialog(mActivity,R.style.ThemeDialogCustom);
dialog.setContentView(messageDialog);
dialog.show();
final Timer t = new Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
if(dialog.isShowing()){
dialog.dismiss();
}
t.cancel();
}
},mSec);
}
});
}
}
For referance
Sets toast to a specific period in milli-seconds:
public void toast(int millisec, String msg) {
Handler handler = null;
final Toast[] toasts = new Toast[1];
for(int i = 0; i < millisec; i+=2000) {
toasts[0] = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toasts[0].show();
if(handler == null) {
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toasts[0].cancel();
}
}, millisec);
}
}
}
I have a custom preference, TimePreference, which extends DialogPreference. It has a custom dialog resource, which looks like this
The source is
#Override
protected void onBindDialogView(View v){
super.onBindDialogView(v);
v.findViewById(R.id.butCancel).setOnClickListener(onClickL);
v.findViewById(R.id.butNow).setOnClickListener(onClickL);
v.findViewById(R.id.butOK).setOnClickListener(onClickL);
//....
}
//...
private final View.OnClickListener onClickL = new View.OnClickListener(){
#Override
public void onClick(View v) {
Log.d(lTag, v + " clicked");
switch (v.getId()) {
case R.id.butOK: saveToSP(false);break;
case R.id.butNow: saveToSP(true);
}
try {
getDialog().dismiss(); //may throw null pointer
} catch (Exception e) { Log.w(lTag, "Exc #onClickL", e); }
}
};
//...
I found a bug where, if you clicked the same preference really fast twice (at the preference screen) two dialogs would open. You could close the first one but, when you would try to close the second, the app would crash. It was a NullPointerException, so I enclosed it in a try-catch block. Now, the exception is caught, but the buttons do not close the dialog. Notice that, by clicking back, it does close.
How can I close the second dialog (possibly by simulating the behaviour of the back button?) ? Note, I want the API level below 10.
Okay, I found a soultion. I have a static boolean, which shows if there is an open dialog.
private static boolean isAnyDialogOpen = false;
On dialog bind, I set it to true,
And after I close the dialog, I set it to false.
Turned out that even this was problematic, but the solution was easier
#Override
protected void onClick() {
if (isAnyDialogOpen)
Log.i(lTag, "there is a dialog already");
else {
isAnyDialogOpen = true;
super.onClick();
}
}
#Override
public void onDismiss(DialogInterface dialog) {
Log.d(lTag, "dismiss, dialog= "+dialog);
isAnyDialogOpen = false;
if (dialog != null) super.onDismiss(dialog);
}
I did this code and want to make a traffic light on and off several times and then stop and choose one of the two lights at random, but the program does the operation, but does not show the changing lights as the operation does
private ImageView redLight;
private ImageView greenLight;
private Button Button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.traffic_lights);
redLight = (ImageView) findViewById(R.id.red_light);
greenLight = (ImageView) findViewById(R.id.green_light);
Button = (Button) findViewById(R.id.start_button);
// Assign click listeners to buttons
Button.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v == Button) {
int flag = 0;
for (int i = 0; i <= 100; i++) {
if (flag == 0) {
turnOnRedLight();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
Log.i("Traffic", "Red");
flag = 1;
} else {
turnOnGreenLight();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
Log.i("Traffic", "Green");
flag = 0;
}
}
}
}
private void turnOnRedLight() {
redLight.setImageResource(R.drawable.red_on);
}
private void turnOnGreenLight() {
greenLight.setImageResource(R.drawable.green_on);
}
}
You are only sleeping for 100ms so you probably aren't seeing the lights change. Change that to something like 1000 or maybe even 500 and you will probably see the change
Thread.sleep(1000);
Also, a couple notes
Although with this code it may not be a problem, sleeping on the UI Thread usually isn't a good idea. Use a Thread and update UI with runOnUiThread(), use AsyncTask, or Handler.
Don't name your Button "Button". Name it something that isn't an Android keyword like button, btn, startButton, startBtn, or something similar.
When distinguishing between which Button was clicked use the Button id instead of the Object. So you would want to change it to
#Override
public void onClick(View v) {
if (v.getId() == (R.id.start_button)) {
you could also use a switch statement here but not important.
I'm wasting a lot of time trying to write this:
private void showAbout() {
Dialog dialog = new Dialog(Generator.this);
dialog.setContentView(R.layout.about);
dialog.setTitle(getString(R.string.about));
dialog.setCancelable(true);
try {
TextView tv_version = (TextView) dialog.findViewById(R.id.tv_version);
tv_version.setText("Version number: " + getPackageManager().getPackageInfo(
getPackageName(), 0).versionName);
TextView tv_createdBy = (TextView) dialog
.findViewById(R.id.tv_createdBy);
tv_createdBy.setText(getString(R.string.made_by));
} catch (NameNotFoundException e) {
Log.e(TAG, "showAbout()", e);
} finally {
dialog.show();
}
}
Over to a class in hope to make my code more readable.
I have written it like this:
private void showAbout() {
About about = new About();
about.show();
}
public class About extends Activity {
String TAG = "About";
Dialog dialog;
/**
*
*/
public About() {
dialog = new Dialog(About.this);
}
public void show() {
dialog.setContentView(R.layout.about);
dialog.setTitle(getString(R.string.about));
dialog.setCancelable(true);
try {
TextView tv_version = (TextView) dialog
.findViewById(R.id.tv_version);
tv_version
.setText("Version number: "
+ getPackageManager().getPackageInfo(
getPackageName(), 0).versionName);
TextView tv_createdBy = (TextView) dialog
.findViewById(R.id.tv_createdBy);
tv_createdBy.setText(getString(R.string.made_by));
} catch (NameNotFoundException e) {
Log.e(TAG, "showAbout()", e);
} finally {
dialog.show();
}
}
}
Bt it doesn't work. It seems like it crashes at the creation of the Dialog, but I have no idea how to write it in another way.
Any ideas?
Given the fact that you want to display about in a pop-up way. Then you're doing it wrong. Extending class to Activity will make it an Activity Class (to be used in activity). You should do something like this:
//class level variable
private Dialog formDialog = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
prepareDialog();
}
/**
* We prepare dialog in it's own method so that we can maintain code separation well.
* I believe there is another <em>better</em> solution. But, it work for now.
*/
private void prepareDialog() {
formDialog = new Dialog(ListDataActivity.this);
formDialog.setContentView(R.layout.form);
formDialog.setTitle("Form Buku");
// set dialog width to fill_parent
LayoutParams formDialogParams = formDialog.getWindow().getAttributes();
formDialogParams.width = LayoutParams.FILL_PARENT;
formDialog.getWindow().setAttributes(
(android.view.WindowManager.LayoutParams) formDialogParams);
txtNama = (EditText) formDialog.findViewById(R.id.txtFormNamaPenulis);
txtNama.setText( "about info" );
btnSimpan = (Button) formDialog.findViewById(R.id.btnFormSimpan);
btnBack.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
formDialog.hide();
}
});
}
Note that you will also need to create new .xml layout for this dialog.
Finally, all you have to do to display it is just call formDialog.show();. This answer is extracted and slightly modified from my android tutorial.
Every example I've seen about extending Activity class includes overriding the onCreatemethod. Therefore, you should add the onCreate method and call it's super method by super.onCreate(savedInstanceState);
I also think that a dialog showing should not be an activity. Dialog is always a part of activity.
You could put the code to create and show the "about" dialog in a base Activity, then have your other Activites extend the base one.