I have a problem with pageviewer. I want to my page scroll every two seconds. I try something like this:
handler.postDelayed(new Runnable() {
public void run() {
viewPager.setCurrentItem(viewPager.getCurrentItem()+1, true);
}
},2000);
But it works only when I start activity. If i put this code to public void onPageSelected(int page) it works but I want to do when I click and manually scroll page I want to stop this handler but it doeasn't work. How I can do that?
You should define your Runnable and Handler like this:
private boolean pagerMoved = false;
private static final long ANIM_VIEWPAGER_DELAY = 2000;
private Handler h = new Handler();
private Runnable animateViewPager = new Runnable() {
public void run() {
if (!pagerMoved) {
viewPager.setCurrentItem(viewPager.getCurrentItem()+1, true);
h.postDelayed(animationFrame, ANIM_VIEWPAGER_DELAY);
}
}
};
Make sure that you setup and tear down in your onPause & onResume methods
#Override
public void onPause() {
super.onPause();
if (h != null) {
h.removeCallbacks(animateViewPager);
}
}
#Override
public void onResume() {
super.onResume();
h.postDelayed(animateViewPager, ANIM_VIEWPAGER_DELAY);
}
Finally, you'll need to listen for a touch event on your viewpager so that you can set pagerMoved to true (which will then stop further automatic page transitions).
Related
I have a fragment that stems off the main activity. I am trying to have a textbox update with the users GPS location as they move around. I currently have it so every time you resume the fragment it updates, but I would like it to happen automatically every 10 seconds or so.
I am currently attempting to use runOnUiThread, which didn't cause my app to crash but didn't seem to do anything.
Within the fragment:
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
TextView newText = getView().findViewById(R.id.wText);
newText.setText(getStringCoordinates);
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
newText.setText(getStringCoordinates);
}
});
}
Try using a handler, something like this should work
private Handler myHandler;
private static final int DELAY = 10000;
#Override
protected void onResume() {
super.onResume();
myHandler = new Handler(Looper.getMainLooper());
checkAgain();
}
private void checkAgain() {
myHandler.postDelayed(()-> checkGps(),DELAY);
}
private void checkGps() {
//do stuff here
checkAgain();
}
#Override
protected void onStop() {
super.onStop();
myHandler.removeCallbacksAndMessages(null);
myHandler = null;
}
basically it sends a message to the main thread every 10 seconds to check gps
the code may be wrong cause I'm writing it off the top of my head, but it should give you a good start
Maybe this is working
public class c_Thread_Update_Fragment extends Thread {
int i =0;
c_Thread_Update_Fragment(FragmentManager fm, ViewPager vp)
{
this.fragmentManager =fm;
this.mViewpager =vp;
}
#Override
public void run() {
while(true)
{
f.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
yourfragmentclass.updateData(i);
}
});
i++;
sleep(1000);
}
}
public static void setFragment(Fragment f){
f =f;
}
}
Implement a public static void update (xxx){} in yourfragmentclass
Use setFragment(f) in your Fragment adapterclass and pass the current fragment.
I need to update a TextView frequently with a specific time delay in the android studio. The code is below. Thank you.
Edit: I also need to end the loop with a button click or with an "if" control.
//INFLATION CALCULATION !!!
/**
* This method calculates Inflation value.
*/
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
}
}, delay*12);
}
Call the same method inside the runnable in order to keep the loop going
Use a flag in order to be able to stop the loop: shouldCalculate
private boolean shouldCalculate = true; // set to false when you want to end the loop
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
if (shouldCalculate) {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
calculateInflation();
}
}
}, delay*12);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
customHandler.postDelayed(this, 0);
}
};
public void startTimer() {
//timer
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public void stopTimer() {
//timer stops
customHandler.removeCallbacks(updateTimerThread);
//timer ends
}
make a reference of runnable thread , start it using startTimer() and remove thread using stopTimer() as you said on a button click or up on a specific conditions .Also you can change the postDelayed milliseconds as ur wish
Try below code. This will do the trick. If you find any problem please let me know.
public void calculateInflation() {
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
if(shouldRepeat)
calculateInflation();
}
}, delay*12);
}
And second approach can be CountDownTimer. Make a method as shown in below code
public void timerTask(final int loopTime){
//Loop time is the actual time for repeatation
new CountDownTimer(loopTime, 1000) {
public void onTick(long millisUntilFinished) {
//this tells you one second is passed
}
public void onFinish() {
//here on time finish you need to define your task
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
//call the same method again for looping
timerTask(loopTime);
}
}.start();
}
Simplest way. Here updateRunnable calls itself with delay. Make updateRunnable as global variable to access from anywhere.
Runnable updateRunnable = new Runnable() {
#Override
public void run() {
inflation = (cpi-cpiIni)/cpiIni*100;
displayInflation();
cpiIni = cpi;
handler.postDelayed(this, UPDATE_TIME);
}
};
Start handler. Here we start handler immediately without delay.
handler.postDelayed(updateRunnable, 0)
Stop handler
handler.removeCallbacks(updateRunnable)
By the way don't forget to stop handler on onDestroy()
I'm stuck in some problems with handlers. In particular, I need to stop and resume a callback either when I respectively turn my device lock and unlock, or when OnPause() and OnResume() are called. I put handler.Post(action) and handler.RemoveCallbacks(action) in OnPause() and in OnResume() but they don't work properly. Actually, when I exit and enter again in my application, It seems that handler.Post(action) is called twice because the update of TextView becomes faster than usual. Besides, the same thing happens when I lock or unlock the device. I dont' know how can I solve this issue.
This is my code:
public class MainActivity : Activity
{
int count = 1;
TextView text;
Handler handler;
myrunnable runnable;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
text = FindViewById<TextView>(Resource.Id.textView1);
handler = new Handler();
runnable = new myrunnable(text, handler);
}
protected override void OnResume()
{
handler.Post(runnable.Run);
base.OnResume();
}
protected override void OnPause()
{
handler.RemoveCallbacks(runnable.Run);
base.OnPause();
}
}
public class myrunnable : Java.Lang.Object, IRunnable
{
int i;
TextView text;
Handler handler;
public myrunnable() { }
public myrunnable(TextView text, Handler handler)
{
this.handler = handler;
this.text = text;
i = 0;
}
public IntPtr Handle
{
get
{
return (IntPtr) 0;
}
}
public void Dispose()
{
}
public void Run()
{
i++;
text.Text = i.ToString();
if (i < 100)
handler.PostDelayed(Run, 1000);
}
}
Thank You in advance.
Im having the same problem. The however, the problem is not the text view it's that onResume is called when the application starts and also when the suspended activity is resumed. Id recommend setting a boolean like canRun that if set false the handler will not post. And if it's true the handler can post and cancel as it pleases. I hope this helps and that im not way off.
EDIT: I've found that what I'm describing below only occurs on my emulated device (Nexus 5, target api 19, 4.4.2 with Intel Atom (x86) cpu), but NOT on my physical device (HTC One)....
EDIT2: Edit1 was due to an IllegalStateException that I didnt catch. Added some code to check if the thread was already running before trying to start it. This combined with the accepted answer resolved my issue.
I have implemented an activty that starts a new thread in the activity's onCreate method, like this:
...
private boolean running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
running = true;
new Thread(null, work, "myThread").start();
}
Runnable work = new Runnable() {
#Override
public void run() {
while (running) {
//Doing work
}
}
};
I'm "pausing" my thread with my activity's onPause method, like this:
#Override
protected void onPause() {
running = false;
super.onPause();
}
So I thought that resuming it would be just as easy...ยจ
#Override
protected void onResume(){
running = true;
super.onResume();
}
but my thread isn't resuming. Any ideas why? Thankful for any help.
Marcus
All of the answers i think have some issues about your running variable because you can not write and read a variable from two different Threads without synchronized block so i post my own answer:
package com.example.threadandtoast;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
public class MonitorObject{
public boolean running = true;
public String message = "";
public boolean mustBePost = true;
}
Thread t;
int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted
// when i pause, you can see it and track it in DDMS
Runnable work = new Runnable() {
boolean myRunning;
#Override
public void run() {
synchronized(mSync) {
myRunning = mSync.running;
}
while (myRunning) {
runOnUiThread(new Runnable() { // in order to update the UI (create Toast)
#Override // we must switch to main thread
public void run() {
// i want to read the message so i must use synchronized block
synchronized(mSync) {
// i use this variable to post a message just for one time because i am in an infinite loop
// if i do not set a limit on the toast i create it infinite times
if(mSync.mustBePost){
Toast.makeText(MainActivity.this, mSync.message, Toast.LENGTH_SHORT).show();
// the message post so i must set it to false
mSync.mustBePost = false;
// if i am going to pause set mSync.running to false so at the end of infinite loop
//of thread he reads it and leaves the loop
if(mSync.message.equals("Main Activity is going to pause")){
mSync.running=false;
}
}
}
}
});
synchronized(mSync) {
myRunning = mSync.running;
}
}
}
};
final MonitorObject mSync = new MonitorObject();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onPause() {
super.onPause();
synchronized(mSync) {
// mSync.running = false; you can not set it here because
// it is possible for the thread to read it and exit the loop before he posts your message
mSync.mustBePost=true;
mSync.message = "Main Activity is going to pause";
}
}
#Override
protected void onResume(){
super.onResume();
threadNameCounter++;
synchronized(mSync) {
mSync.running = true;
mSync.mustBePost=true;
mSync.message = "Main Activity is going to resume";
}
t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
t.start();
}
}
Or you can use this code:
public class MainActivity extends ActionBarActivity {
Thread t;
int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted
// when i pause, you can see it in DDMS
String message = "";
boolean isPost = false;
Runnable work = new Runnable() {
#Override
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if(!isPost){
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
isPost = true;
if( message.equals("Main Activity is going to pause")){
t.interrupt();
}
}
}
});
if(Thread.currentThread().isInterrupted()){
break;
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onPause() {
super.onPause();
message = "Main Activity is going to pause";
isPost = false;
}
#Override
protected void onResume(){
super.onResume();
message = "Main Activity is going to resume";
isPost = false;
threadNameCounter++;
t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
t.start();
}
}
you can also use semaphore or wait-notify approach.
i put public String message = ""; and public boolean mustBePost = true; in to mSync object but it is
not necessary because only main thread have an access to them.
if you have any problem please ask.
The statement running = false; will stop execution of the Thread, instead of pausing it. Use two variables: One for stopping current Thread, and another for pausing and resuming the Thread, as follow:
boolean isThreadPause=false;
Runnable work = new Runnable() {
#Override
public void run() {
while (running) {
if (!isThreadPause) {
// Doing work
}
}
}
};
In the onPause event of the Activity, set isThreadPause to true, and in the onResume event, set isThreadPause to false.
This is because your Runnable object stops when the while loop stops. You could try this:
Runnable work = new Runnable() {
#Override
public void run() {
while () {
if(running){
//Doing work
}
}
}
};
I have a layout displayed on a button click.I want to hide that layout after 10 seconds.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mVolHandler = new Handler();
mVolRunnable = new Runnable() {
public void run() {
mVolLayout.setVisibility(View.GONE);
}
};
}
private OnTouchListener mVolPlusOnTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mVolLayout.setVisibility(View.VISIBLE);
mVolHandler.postDelayed(mVolRunnable, 10000);
}
}
Make use of Handler & Runnable.
You can delay a Runnable using postDelayed of Handler.
Runnable mRunnable;
Handler mHandler=new Handler();
mRunnable=new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
yourLayoutObject.setVisibility(View.INVISIBLE); //If you want just hide the View. But it will retain space occupied by the View.
yourLayoutObject.setVisibility(View.GONE); //This will remove the View. and free s the space occupied by the View
}
};
Now inside onButtonClick event you have to tell Handler to run a runnable after X milli seconds:
mHandler.postDelayed(mRunnable,10*1000);
If you want to cancel this then you have to use mHandler.removeCallbacks(mRunnable);
Update (According to edited question)
You just need to remove callbacks from Handler using removeCallbacks()
So just update your code inside onTouch method like this :
mVolLayout.setVisibility(View.VISIBLE);
mVolHandler.removeCallbacks(mVolRunnable);
mVolHandler.postDelayed(mVolRunnable, 10000);
You can use an Animation started when you click the button, with 10 seconds duration that fades out the layout and probably sets its visibility to GONE at the end.
You can use postDelayed:
val delay = 3000L // 3 seconds
view.postDelayed({ view.visibility = View.GONE }, delay)
Use Handler to hide layout after 10 seconds. Use Post delayed method
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
pd=ProgressDialog.show(this,"","Loading, Please wait .. ",true);
setTitle("set title");
final Handler uiThreadCallback=new Handler();
final Runnable runInUIThread= new Runnable(){
public void run(){
fnDraw();
pd.dismiss();
}
};
new Thread(){
#Override public void run(){
uiThreadCallback.post(runInUIThread);
}
}.start();
}
public void fnDraw(){
setContentView(R.layout.define ur xml if any);
i1=(ImageView)findViewById(R.id.i1);
t1=(TextView)findViewById(R.id.t1);
t2=(TextView)findViewById(R.id.t2);
timerRegister=new Timer();
lIteration=0;
checkTime=new TimerTask(){
public void run(){
if(lIteration==1){
timerRegister.cancel();
uiDrawThreadCallback.post(runInUIDrawThread);
}
lIteration++;
return;
}
};
timerRegister.scheduleAtFixedRate(checkTime,0,10000);
}
final Handler uiDrawThreadCallback=new Handler();
final Runnable runInUIDrawThread= new Runnable(){
#Override
public void run(){
fnDrawAgain();
}
};
public void fnDrawAgain(){
Intent intent=new Intent(this,new class you want to open.class);
startActivity(intent);
}
}
try it m sure it gonna work in ur on create screen