Unity VR autoclick after few seconds - android

I am using the GoogleVR package and I have this reticle which works (in the sense that it makes an object I am looking at bigger). The behavior I would like, is to click by looking on object for about three seconds. The object currently has an event trigger, but how can I wait for three seconds and then click?

When you look at the object, the trigger is activated right?
Then when you detect the trigger up just make a function that waits for 3 seconds and and then do what you want.
Dont forget to stop the wait if the user starts looking somewhere else.

I wrote this script a while ago, it works fine with buttons:
[RequireComponent(typeof(Button))]
public class InteractiveItem : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
public Image progressImage; // add an image as child of button and set its image type to Filled. And assign it here.
public bool isEntered = false;
float GazeActivationTime = 3f;
float timeElapsed;
Button _button;
void Start ()
{
_button = GetComponent<Button>();
}
void fillProgress(float value)
{
if (progressImage != null)
{
progressImage.fillAmount = value;
}
}
void Update ()
{
if(isEntered)
{
timeElapsed += Time.deltaTime;
fillProgress(Mathf.Clamp(timeElapsed/GazeActivationTime,0,1));
if(timeElapsed >= GazeActivationTime)
{
timeElapsed = 0;
_button.onClick.Invoke();
fillProgress(0);
isEntered = false;
}
}
else
{
timeElapsed = 0;
}
}
void OnDisable()
{
if (this.enabled)
{
isEntered = false;
fillProgress(0);
}
}
#region IPointerEnterHandler implementation
public void OnPointerEnter (PointerEventData eventData)
{
if (_button.IsInteractable())
{
isEntered = true;
}
}
#endregion
#region IPointerExitHandler implementation
public void OnPointerExit (PointerEventData eventData)
{
if (!_button.IsInteractable())
return;
try
{
isEntered = false;
fillProgress(0);
}
catch (System.Exception ex)
{
Debug.LogError(ex.Message);
}
}
#endregion
#region IPointerClickHandler implementation
public void OnPointerClick (PointerEventData eventData)
{
isEntered = false;
timeElapsed = 0;
fillProgress(0);
}
#endregion
}

Related

Unity2d android detecting touches

How to detect touches and long touches on buttons in unity for android?
I have already tried this function but it returns true if i touch any place on screen:
bool checkTouch()
{
for(int i = 0; i < Input.touchCount; i++)
{
TouchPhase tp = Input.GetTouch(i).phase;
if(tp == TouchPhase.Began || tp == TouchPhase.Ended || tp == TouchPhase.Stationary)
return true;
}
return false;
}
One way to achieve Buttons that allow that, is to create your own button, implementing the necessary interfaces like IPointerDownHandler, IPointerUpHandler.
That way you could manage how will the button act, here is an example:
using UnityEngine;
using UnityEngine.EventSystems;
public class LongClickButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
private bool pointerDown;
private float pointerDownTimer;
[SerializeField]
private float requiredHoldTime;
public void OnPointerDown(PointerEventData eventData)
{
pointerDown = true;
Debug.Log("OnPointerDown");
}
public void OnPointerUp(PointerEventData eventData)
{
Reset();
Debug.Log("OnPointerUp");
}
private void Update()
{
if (pointerDown)
{
pointerDownTimer += Time.deltaTime;
if (pointerDownTimer >= requiredHoldTime)
{
//do your LongClick stuff
Debug.Log("LongClick");
Reset();
}
}
}
private void Reset()
{
pointerDown = false;
pointerDownTimer = 0;
}
}
Remember to attach the script to a GameObject that can be interactable, like an Image.

Cancel the runnable/handler in a custom view when the activity pauses

I have a custom view that has a blinking cursor. I make the blinking cursor using a Handler and posting a Runnable to it after a 500 milisecond delay.
When the activity that the view is in, I want to stop the blinking by removing the callbacks on the handler. However, I've noticed that when I switch to another app, the handler/runnable keep going, ie, the log says it is still blinking.
If I had control of the view I would just do something like this
#Override
protected void onPause() {
handler.removeCallbacks(runnable);
super.onPause();
}
But my custom view will be part of a library and so I don't have control over the Activities that other developers use my custom view in.
I tried onFocusChanged, onScreenStateChanged, and onDetachedFromWindow but none of these work for when the user switches to another app.
Here is my code. I simplified it by removing anything not pertinent to the problem.
public class MyCustomView extends View {
static final int BLINK = 500;
private Handler mBlinkHandler;
private void init() {
// ...
mBlinkHandler = new Handler();
mTextStorage.setOnChangeListener(new MongolTextStorage.OnChangeListener() {
#Override
public void onTextChanged(/*...*/) {
// ...
startBlinking();
}
});
}
Runnable mBlink = new Runnable() {
#Override
public void run() {
mBlinkHandler.removeCallbacks(mBlink);
if (shouldBlink()) {
// ...
Log.i("TAG", "Still blinking...");
mBlinkHandler.postDelayed(mBlink, BLINK);
}
}
};
private boolean shouldBlink() {
if (!mCursorVisible || !isFocused()) return false;
final int start = getSelectionStart();
if (start < 0) return false;
final int end = getSelectionEnd();
if (end < 0) return false;
return start == end;
}
void startBlinking() {
mBlink.run();
}
void stopBlinking() {
mBlinkHandler.removeCallbacks(mBlink);
}
#Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (focused) {
startBlinking();
} else {
stopBlinking();
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
#Override
public void onScreenStateChanged(int screenState) {
switch (screenState) {
case View.SCREEN_STATE_ON:
startBlinking();
break;
case View.SCREEN_STATE_OFF:
stopBlinking();
break;
}
}
public void onAttachedToWindow() {
super.onAttachedToWindow();
startBlinking();
}
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
stopBlinking();
}
}
I guess you are starting the thread separately using thread.run(), instead just make a method and call it recursively Something like this:
public void blink(){
mBlinkHandler.postDelayed(mBlink, BLINK);
}
And in the runnable:
Runnable mBlink = new Runnable() {
#Override
public void run() {
mBlinkHandler.removeCallbacks(mBlink);
if (shouldBlink()) {
// ...
Log.i("TAG", "Still blinking...");
blink();
}
}
};
As you are directly starting the thread using run method. So it won't stop by removing callbacks.
Hope this helps.
I solved the problem by following #pskink's advice in the comments and adapted the code from Android 1.6. This may be an old version of Android but the blinking cursor part works well for my purposes. Overriding onWindowFocusChanged was the key.
My full code is on GitHub. Here are the pertinent parts:
public class MyCustomView extends View {
private boolean mCursorVisible = true;
private Blink mBlink;
private long mShowCursor; // cursor blink timing based on system clock
static final int BLINK = 500;
#Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
mShowCursor = SystemClock.uptimeMillis();
if (focused) {
makeBlink();
}
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
#Override
protected void onDraw(Canvas canvas) {
int start = getSelectionStart();
int end = getSelectionEnd();
// draw the blinking cursor on top
if (start == end && blinkShouldBeOn()) {
canvas.drawRect(getCursorPath(start), mCursorPaint);
}
}
private boolean blinkShouldBeOn() {
if (!mCursorVisible || !isFocused()) return false;
return (SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK;
}
private void makeBlink() {
if (!mCursorVisible) {
if (mBlink != null) {
mBlink.removeCallbacks(mBlink);
}
return;
}
if (mBlink == null)
mBlink = new Blink(this);
mBlink.removeCallbacks(mBlink);
mBlink.postAtTime(mBlink, mShowCursor + BLINK);
}
public void setCursorVisible(boolean visible) {
mCursorVisible = visible;
invalidateCursorPath();
if (visible) {
makeBlink();
} else if (mBlink != null) {
mBlink.removeCallbacks(mBlink);
}
}
#Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus) {
if (mBlink != null) {
mBlink.uncancel();
if (isFocused()) {
mShowCursor = SystemClock.uptimeMillis();
makeBlink();
}
}
} else {
if (mBlink != null) {
mBlink.cancel();
}
hideSystemKeyboard();
}
}
private static class Blink extends Handler implements Runnable {
private WeakReference<MongolEditText> mView;
private boolean mCancelled;
Blink(MongolEditText v) {
mView = new WeakReference<>(v);
}
public void run() {
if (mCancelled) {
return;
}
removeCallbacks(Blink.this);
MongolEditText met = mView.get();
if (met != null && met.isFocused()) {
int st = met.getSelectionStart();
int en = met.getSelectionEnd();
if (st == en && st >= 0 && en >= 0) {
if (met.mLayout != null) {
met.invalidateCursorPath();
}
postAtTime(this, SystemClock.uptimeMillis() + BLINK);
}
}
}
void cancel() {
if (!mCancelled) {
removeCallbacks(Blink.this);
mCancelled = true;
}
}
void uncancel() {
mCancelled = false;
}
}
}

valueanimator.start is restaring the animation after valueanimator.cancel on API < 19

i know this is asked before i tried all the solution but i cannot arrive to fix it,
i have objects that fall from the top of the screen to the bottom of the screen using translation in android library.
i want to the pause the animation and resume it:
PAUSE CODE fixed from the suggestion on one of the stack overflow posts:
private void pauseAnimation() {
p = true;
Pausearray = new MyClass[mAllImageViews.size()];
int count = 0;
for (ArrowView v : mAllImageViews) {
ValueAnimator va = (ValueAnimator) v.getTag();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
va.pause();
} else {
if (va != null) {
MyClass temp = new MyClass();
temp.tag = v.getTag().toString();
temp.playtime = va.getCurrentPlayTime();
Pausearray[count] = temp;
va.cancel();
}
}
count ++;
}
}
the pause is working the annimation is stoping from moving and its staying in its position.
RESUME CODE suggested by one of the stack overflow posts:
private void resumeAnimation() {
p = false;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
for (ArrowView v : mAllImageViews) {
try {
ValueAnimator va = (ValueAnimator) v.getTag();
va.resume();
} catch (Exception ex) {
}
}
} else {
if(Pausearray!=null) {
for (ArrowView v : mAllImageViews) {
ValueAnimator va = (ValueAnimator) v.getTag();
for (int i = 0; i < Pausearray.length; i++) {
if(v.getTag().toString().equalsIgnoreCase(Pausearray[i].tag)){
va.start();
va.setCurrentPlayTime(Pausearray[i].playtime);
}
}
}
}
}
}
the problem with the resume that it's starting from the top again i want it to continue where it was it's position on screen. Thank you!
Update:
i tried to get the arrow view position from screen and set it at resume, i'm still getting the same issue, views are restarting so the edited code is:
private void resumeAnimation() {
p = false;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
for (ArrowView v : mAllImageViews) {
try {
ValueAnimator va = (ValueAnimator) v.getTag();
va.resume();
} catch (Exception ex) {
}
}
} else {
if(Pausearray!=null) {
for (ArrowView v : mAllImageViews) {
ValueAnimator va = (ValueAnimator) v.getTag();
for (int i = 0; i < Pausearray.length; i++) {
if(v.getTag().toString().equalsIgnoreCase(Pausearray[i].tag)){
Log.w("PAUSETEST","Setting Parameters "+Pausearray[i].playtime);
va.start();
va.setCurrentPlayTime(Pausearray[i].playtime);
v.setY(Pausearray[i].translationy); // i took the location via v.gettranslationY on pause
}
}
}
}
}
}
UPDATE:
i heard while i was searching that valueanimator doesn't restart so i switched the valueanimator to object animator animator code:
public void startAnimation(final ArrowView aniView) {
aniView.setPivotX(aniView.getWidth());
aniView.setPivotY(aniView.getHeight());
long delay = new Random().nextInt(Constants.MAX_DELAY);// generate a random delay time before the animation starts to go down
ObjectAnimator animator = ObjectAnimator.ofFloat(aniView,"translationY", mDisplaySize.bottom - (buttonsize) - (90 * mScale));
if (aniView.getColor() == 0 && aniView.draw == false) {
Constants.ANIM_DURATION = Constants.ANIM_DURATION_NORMAL;
} else if (aniView.getColor() != 0 && aniView.draw == false) {
Constants.ANIM_DURATION = Constants.ANIM_DURATION_COLOR;
} else if (aniView.getColor() == 0 && aniView.draw == true) {
Constants.ANIM_DURATION = Constants.ANIM_DURATION_COLOR;
} else if (aniView.getColor() != 0 && aniView.draw == true) {
Constants.ANIM_DURATION = Constants.ANIM_DURATION_COLORANDCALC;
}
animator.setDuration(Constants.ANIM_DURATION);// speed of the falldown
animator.setInterpolator(new AccelerateInterpolator());
animator.setStartDelay(delay);// start the animation after the delay.
// animator.addUpdateListener(new AnimatorUpdateListener() {
//
// //int angle = 50 + (int) (Math.random() * 101);
// //int movex = new Random().nextInt(mDisplaySize.right);
//
// #Override
// public void onAnimationUpdate(ValueAnimator animation) {
// float value = ((Float) (animation.getAnimatedValue())).floatValue();
// //aniView.setRotation(angle*value);
// //aniView.setTranslationX((movex-40)*value);
// aniView.setTranslationY((mDisplaySize.bottom - (buttonsize)) * value - (90 * mScale));// set the translation to fall down and stop on the top of buttons
// }
// });
aniView.setTag(animator);
animator.start();
}
and i changed the code of the pause/resume to cast it into object animator and I'm still facing the same problem... on start is restarting the animation! please someone help! thanks!
After Playing around with valueanimator class i figured out a trick to make the animation stop, and resume its not an authentic way, but it solves the problem, i extended from value animator class and replaced the normal animator in my main class with the myvalueanimator class and here the play around in the value animator class:
import android.animation.ValueAnimator;
import android.util.Log;
import java.util.Timer;
/**
* Created by win7 on 6/21/2017.
*/
public class MyValueAnimator extends ValueAnimator {
private float animatedValue = 0;
private long currenttime;
private long totaltime;
private boolean onetime = true;
private volatile boolean mPaused = false;
private Timer t;
public void pause() {
animatedValue = (float) getAnimatedValue();
mPaused = true;
}
// #Override
// public void setValues(PropertyValuesHolder... values) {
// if (mPaused)
// return;
// super.setValues(values);
#Override
public Object getAnimatedValue() {
if (mPaused) {
if(onetime){
currenttime = getCurrentPlayTime();
// totaltime = getStartDelay()+ (getDuration() * (getRepeatCount() + 1));
totaltime = getDuration();
setDuration(Long.parseLong("9999999999999999"));
Log.w("PauseDur",Long.parseLong("9999999999999999")+"");
onetime =false;
}
return animatedValue;
}
return super.getAnimatedValue();
}
public void resume() {
mPaused = false;
onetime=true;
setCurrentPlayTime(currenttime);
setDuration(totaltime);
}
public MyValueAnimator(float from, float to) {
setFloatValues(from, to);
}
}

Android, terminate threads when activity paused or stopped?

I have an activity like below. I want the threads inside the activity terminate when the activity is paused or stopped. I searched and found volatile Boolean solution which didn't work for me. When i put the activity in pause or stop state, download continues, which i don't want it.
public class MyActivity extends Activity {
//some code here
private void foo(){
new Thread (new Runnable (){
#Override
public void run() {
//download something from internet
}
}).start();
}
}
i used this pattern which didn't work:
public class MyActivity extends Activity {
volatile Boolean state = true;
//some code here
private void foo(){
new Thread (new Runnable (){
#Override
public void run() {
while (state) {
//download something from internet
}
}
}).start();
}
#Override
public void onPause(){
super.onPause();
state = false;
}
#Override
public void onStop(){
super.onStop();
state = false;
}
}
Here's an example of the structure of a thread which stops when back is hit, which I made for my game (and works). One key difference is you're using a thread in your Activity, while in mine I call a View in my Activity and run the thread in the View. If I hit back, I return to my Activity, and can call the thread again by hitting 'start.' BECAUSE my thread behaves the way you want yours too, even if it's happening in View, I thought you may find it helpful.
Where my of my synchronization happens is with the touchscreen values, and making sure those are updated in the thread and calling function.
The thread is trashed totally unless you have a way of saving the state (if you need to).
Your thread will need to synchronize with other functions you want controlling/sharing values with the thread, like onPause, etc..
**you'll need to have some synchronized test value inside your while loop which can then change state to false, otherwise the thread will continue on its own, which is the point of threads.
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private final GameActivity gameActivity;
private GameThread _thread;
private boolean previouslyRunning = false;
private int width; //Screen width
private int height; //Screen height
private boolean newGame = true;
public GameView(Context context) {
super(context);
getHolder().addCallback(this);
this.gameActivity = (GameActivity) context;
_thread = new GameThread(getHolder(), this);
setFocusable(true);
setFocusableInTouchMode(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w;
height = h;
super.onSizeChanged(w, h, oldw, oldh);
//_thread.initialize();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!previouslyRunning) {
_thread = new GameThread(getHolder(), this);
_thread.initialize();
}
_thread.setRunning(true);
_thread.start();
previouslyRunning = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//TODO - this was an Auto-generated method stub...
//TODO - research what this might be useful for
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
//Put stuff that needs destructed here.
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// will will try again and again
//TODO: figure it out....
}
}
}
public boolean onTouchEvent(MotionEvent event) {
int numPointers = event.getPointerCount();
int ptrIdx = 0;
int touch = event.getActionMasked();
if (touch == MotionEvent.ACTION_DOWN) {
while (ptrIdx < numPointers) {
int id = event.getPointerId(ptrIdx);
float xp = event.getX(ptrIdx) / width;
if (xp > 0.6) {
_thread.shieldFront = false;
}
if (xp > 0.6 && !attacks) {
attacks = true;
_thread.attackandDefendToggle(true);
} else if (xp > 0.6 && attacks) {
attacks = false;
_thread.attackandDefendToggle(false);
} else if ((xp < 0.4 && xp > 0.2) && !movedRight) {
movedRight = true;
_thread.moveRight(true);
} else if ((xp < 0.4 && xp > 0.2) && movedRight) {
movedRight = false;
_thread.moveRight(false);
} else if (xp < 0.2 && !movedLeft) {
movedLeft = true;
_thread.moveLeft(true);
} else if (xp < 0.2 && movedLeft) {
movedLeft = false;
_thread.moveLeft(false);
}
ptrIdx++;
}
}
if (touch == MotionEvent.ACTION_UP) {
_thread.moveLeft(false);
_thread.moveRight(false);
_thread.attackandDefendToggle(false);
attacks = false;
_thread.shieldFront = true;
}
return true;
}
class GameThread extends Thread {
/****************************
* Public functions *
****************************/
public GameThread(SurfaceHolder surfaceHolder, GameView panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
// put sounds here.
soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
//more sounds later
//TODO: create sounds
}
/************************************************
* update() function updates all variables, *
* such as physics, Canvas draw points, score *
* life, etc.. It is called before draw. *
************************************************/
private void update() {
// all the values I want updated with each callback
}
/************************************************
* draw() function creates images on screen, *
* but it performs no logic. *
************************************************/
private void draw(Canvas canvas) {
if (canvas == null) {
return;
}
//Draw stuff on screen
}
public void initialize() {
// Values I want the program to start with;
}
public void setRunning(boolean run) {
_run = run;
}
//Code below actually runs the thread.
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
// Update the game state
update();
// Draw image
draw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}

Draw mathematical function with "androidPlot" library

I want to draw math-function like y=x^2+1 with androidPlot library.I have "SimpleXYPlot". It works but I don't know how to change it from sin to my function.
Here's the code:
public class DynamicXYPlotActivity extends Activity {
// redraws a plot whenever an update is received:
private class MyPlotUpdater implements Observer {
Plot plot;
public MyPlotUpdater(Plot plot) {
this.plot = plot;
}
#Override
public void update(Observable o, Object arg) {
plot.redraw();
}
}
private XYPlot dynamicPlot;
private MyPlotUpdater plotUpdater;
SampleDynamicXYDatasource data;
private Thread myThread;
#Override
public void onCreate(Bundle savedInstanceState) {
// android boilerplate stuff
super.onCreate(savedInstanceState);
setContentView(R.layout.dynamicxyplot_example);
// get handles to our View defined in layout.xml:
dynamicPlot = (XYPlot) findViewById(R.id.dynamicXYPlot);
plotUpdater = new MyPlotUpdater(dynamicPlot);
// only display whole numbers in domain labels
dynamicPlot.getGraphWidget().setDomainValueFormat(new DecimalFormat("0"));
// getInstance and position datasets:
data = new SampleDynamicXYDatasource();
SampleDynamicSeries sine1Series = new SampleDynamicSeries(data, 0, "Sine 1");
SampleDynamicSeries sine2Series = new SampleDynamicSeries(data, 1, "Sine 2");
LineAndPointFormatter formatter1 = new LineAndPointFormatter( Color.rgb(0, 0, 0), null, null, null );
formatter1.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
formatter1.getLinePaint().setStrokeWidth(10);
dynamicPlot.addSeries( sine1Series,formatter1 );
LineAndPointFormatter formatter2 = new LineAndPointFormatter(Color.rgb(0, 0, 200), null, null, null);
formatter2.getLinePaint().setStrokeWidth(10);
formatter2.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
//formatter2.getFillPaint().setAlpha(220);
dynamicPlot.addSeries(sine2Series, formatter2);
// hook up the plotUpdater to the data model:
data.addObserver(plotUpdater);
// thin out domain tick labels so they dont overlap each other:
dynamicPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL);
dynamicPlot.setDomainStepValue(5);
dynamicPlot.setRangeStepMode(XYStepMode.INCREMENT_BY_VAL);
dynamicPlot.setRangeStepValue(10);
dynamicPlot.setRangeValueFormat(new DecimalFormat("###.#"));
// uncomment this line to freeze the range boundaries:
dynamicPlot.setRangeBoundaries(-100, 100, BoundaryMode.FIXED);
// create a dash effect for domain and range grid lines:
DashPathEffect dashFx = new DashPathEffect(
new float[] {PixelUtils.dpToPix(3), PixelUtils.dpToPix(3)}, 0);
dynamicPlot.getGraphWidget().getDomainGridLinePaint().setPathEffect(dashFx);
dynamicPlot.getGraphWidget().getRangeGridLinePaint().setPathEffect(dashFx);
}
#Override
public void onResume() {
// kick off the data generating thread:
myThread = new Thread(data);
myThread.start();
super.onResume();
}
#Override
public void onPause() {
data.stopThread();
super.onPause();
}
class SampleDynamicXYDatasource implements Runnable {
// encapsulates management of the observers watching this datasource for update events:
class MyObservable extends Observable {
#Override
public void notifyObservers() {
setChanged();
super.notifyObservers();
}
}
private static final double FREQUENCY = 5; // larger is lower frequency
private static final int MAX_AMP_SEED = 100; //100
private static final int MIN_AMP_SEED = 10; //10
private static final int AMP_STEP = 1;
public static final int SINE1 = 0;
public static final int SINE2 = 1;
private static final int SAMPLE_SIZE = 30;
private int phase = 0;
private int sinAmp = 1;
private MyObservable notifier;
private boolean keepRunning = false;
{
notifier = new MyObservable();
}
public void stopThread() {
keepRunning = false;
}
//#Override
public void run() {
try {
keepRunning = true;
boolean isRising = true;
while (keepRunning) {
Thread.sleep(100); // decrease or remove to speed up the refresh rate.
phase++;
if (sinAmp >= MAX_AMP_SEED) {
isRising = false;
} else if (sinAmp <= MIN_AMP_SEED) {
isRising = true;
}
if (isRising) {
sinAmp += AMP_STEP;
} else {
sinAmp -= AMP_STEP;
}
notifier.notifyObservers();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int getItemCount(int series) {
return SAMPLE_SIZE;
}
public Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index;
}
public Number getY(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
double angle = (index + (phase))/FREQUENCY;
double amp = sinAmp * Math.sin(angle);
switch (series) {
case SINE1:
return amp;
case SINE2:
return -amp;
default:
throw new IllegalArgumentException();
}
}
public void addObserver(Observer observer) {
notifier.addObserver(observer);
}
public void removeObserver(Observer observer) {
notifier.deleteObserver(observer);
}
}
class SampleDynamicSeries implements XYSeries {
private SampleDynamicXYDatasource datasource;
private int seriesIndex;
private String title;
public SampleDynamicSeries(SampleDynamicXYDatasource datasource, int seriesIndex, String title) {
this.datasource = datasource;
this.seriesIndex = seriesIndex;
this.title = title;
}
#Override
public String getTitle() {
return title;
}
#Override
public int size() {
return datasource.getItemCount(seriesIndex);
}
#Override
public Number getX(int index) {
return datasource.getX(seriesIndex, index);
}
#Override
public Number getY(int index) {
return datasource.getY(seriesIndex, index);
}
}
}
=======================================================
After what "Nick" said and other minor addition, I got this result:
but as we know :
https://www.google.com/search?q=y%3Dx%5E2%2B1&oq=y%3Dx%5E2%2B1&aqs=chrome..69i57j0l5.7056j0j7&sourceid=chrome&es_sm=93&ie=UTF-8
Now how to make the left side?
Using the code above can modify SampleDynamicXYDatasource to do what you want. All that code does is generate some data in a sine pattern. I don't know how your x values are going to be generated so here's a modified SampleDynamicXYDatasource.getY(...) that just uses the original code where x=index above and uses your function to generate the y-values:
public Number getY(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
Number x = getX(series, index);
double y = Math.pow(x.doubleValue(), 2) + 1;
switch (series) {
case SINE1:
return y;
case SINE2:
return -y;
default:
throw new IllegalArgumentException();
}
}
You'll notice that when you make this change, the plot appears to no longer be animated. (it actually still is but that's besides the point) This is because y is now purely a function of x and the x values never change.
As far as how to stop the animation, the plot redraws whenever plot.redraw() is called, which in the example above is in response to an event being continuously fired by events generated by the thread being run on the Runnable instance of SampleDynamicXYDatasource. Using the example above, the simplest way to stop the animation is to replace:
#Override
public void onResume() {
// kick off the data generating thread:
myThread = new Thread(data);
myThread.start();
super.onResume();
}
with:
#Override
public void onResume() {
dynamicPlot.redraw();
super.onResume();
}
Try replace this>>
public Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index;
}
To this>>
public Number getX(int series, int index) {
if (index >= SAMPLE_SIZE) {
throw new IllegalArgumentException();
}
return index - 15;
}

Categories

Resources