Animate image Button in circular motion - android

I'm trying to animate an image button with ObjectAnimator to move in a circular motion
PropertyValuesHolder tranX = PropertyValuesHolder.ofFloat(View.TRANSLATION_X, path);
PropertyValuesHolder tranY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, path);
ObjectAnimator scaleAnimation =
ObjectAnimator.ofPropertyValuesHolder(scaleButton, pvhX, pvhY);
scaleAnimation.setRepeatCount(1);
scaleAnimation.setRepeatMode(ValueAnimator.REVERSE);
I tried to make a path with :
Path path_x = new Path();
Path path_y = new Path();
for(i = 0; i < 2* Math.PY; i += 0.1)
{
\\save a path with cos and sin
}
but i don't know with what method to use inside the for loop
if it's even possible
I would try any other way to do create the circular motion

Related

How can i change text rotation in Luck Wheel (Android)

Here the link of GitHub Code https://github.com/thanhniencung/LuckyWheel
I try to change the rotation of canvas using this piece of code
private void drawText(Canvas canvas, float tmpAngle, float sweepAngle, String mStr) {
Path path = new Path();
path.addArc(mRange,tmpAngle,sweepAngle);
float textWidth = mTextPaint.measureText(mStr);
int hOffset = (int) (mRadius * Math.PI / mLuckyItemList.size()/2-textWidth/2);
int vOffset = mRadius/2/4;
canvas.drawTextOnPath(mStr, path, hOffset, vOffset, mTextPaint);
}
I want to change orientation of text like picture shown below
In the latest version of the LuckyWheel, when initialising LuckyItems data, you can set the values for luckyItem.secondaryText instead of luckyItem.topText, and you will have the wanted text orientation.
Like this:
List<LuckyItem> data = new ArrayList<>();
for (int i = 0; i < sectorsTitles.length; i++) {
LuckyItem luckyItem = new LuckyItem();
// luckyItem.topText = sectorsTitles[i]; // Don't use this
luckyItem.secondaryText = sectorsTitles[i]; // Use this instead
luckyItem.color = Color.parseColor(ROULETTE_COLORS[i]);
data.add(luckyItem);
}
luckyWheelView.setData(data);
In XML code you can change the rotation by using
android:rotation="120" (Then any angle you want positive or negative)
But, you may need to rotate this image when it is in the bottom and then rotate it again when it is in the top. So you can rotate it programatically whenever you want.
TextView textView = findViewById(R.id.textView);
ImageView imageView = findViewById(R.id.imageView);
textView.setRotation(120);
imageView.setRotation(120);
And then if you want to comeback it latter to the position it was in the beginning. You just add the negative sign.
textView.setRotation(-120);
imageView.setRotation(-120);
Of course, the angle is up to you.

In Android how to use ObjectAnimator to move to point x along a curve

I have an image view "stone" and am moving it from its current position to a X,Y position. I want it to move along a curve. Please let me know how I can do that(i have set the min api as 11)
ObjectAnimator moveX = ObjectAnimator.ofFloat(stone, "x", catPos[0] );
ObjectAnimator moveY = ObjectAnimator.ofFloat(stone, "y", catPos[1] );
AnimatorSet as = new AnimatorSet();
as.playTogether(moveX, moveY);
as.start();
The answer by Budius seems perfectly useful to me.
Here are the animator objects I use:
Purpose: Move View "view" along Path "path"
Android v21+:
// Animates view changing x, y along path co-ordinates
ValueAnimator pathAnimator = ObjectAnimator.ofFloat(view, "x", "y", path)
Android v11+:
// Animates a float value from 0 to 1
ValueAnimator pathAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
// This listener onAnimationUpdate will be called during every step in the animation
// Gets called every millisecond in my observation
pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
float[] point = new float[2];
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Gets the animated float fraction
float val = animation.getAnimatedFraction();
// Gets the point at the fractional path length
PathMeasure pathMeasure = new PathMeasure(path, true);
pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null);
// Sets view location to the above point
view.setX(point[0]);
view.setY(point[1]);
}
});
Similar to: Android, move bitmap along a path?
you have two options:
both needs a Path object that defines your curve:
Path path = new Path();
path. // define your curve here
if using Lollipop only (API 21) use ObjectAnimator.ofFloat(...path) like this:
ObjectAnimator.ofFloat(stone, View.X, View.Y, path).start();
if that's not an options, you use an AnimatorListener to receive updates about the each animator frame and use the PathMeasure to get the values on that point, like this:
PathMeasure pm;
float point[] = {0f, 0f};
private final ValueAnimator.AnimatorUpdateListener listener =
new ValueAnimator.AnimatorUpdateListener(){
#Override
public void onAnimationUpdate (ValueAnimator animation) {
float val = animation.getAnimatedFraction();
pm.getPosTan(pm.getLength() * val, point, null);
stone.setTranslationX(point[0]);
stone.setTranslationY(point[1]);
}
}
// and then to animate
pm = new PathMeasure(path, false);
ValueAnimator a = ValueAnimator.ofFloat(0.0f 1.0f);
a.setDuration(/* your duration */);
a.setInterpolator(/* your interpolator */);
a.addUpdateListener(listener);
a.start();
Play around with the interpolators. For example set 2 different Interpolators for x and y :
moveX.setInterpolator(new AccelerateDecelerateInterpolator());
moveY.setInterpolator(new DecelerateInterpolator());
Theres more (LinearInterpolator, AccelerateInterpolator...) but I think this should be the combination you want.
Thanks for the answers, but I found my own answer.Just added some extra x,y positions in the Objectanimator stmt. It went to those positions before coming to the final one and traced a path!
ObjectAnimator moveX = ObjectAnimator.ofFloat(stone, "x", catPos[0]-20,catPos[0]-10,catPos[0] );
ObjectAnimator moveY = ObjectAnimator.ofFloat(stone, "y",catPos[1]-20,catPos[1]-10, catPos[1] );
The Path class has methods for creating non-straight lines of several types; arcs, circles, ovals, rectangles, cubic & quadratic bezier curves, which you can then animate your object along.
As Budius points out, you do need to code for API 21 (Lollipop) or later to use paths with object translation. It is now over two years old.
On the other hand, there does seem a dearth of anything-more-than-very-simple examples of using paths "in the wild", so perhaps there's a reason they've not caught on yet.
Check this link for 3 ways of animating several properties of a View in parallel:
https://developer.android.com/guide/topics/graphics/prop-animation#view-prop-animator
The 1st way of doing it is using AnimatorSet.
Below is the 2nd way:
public static ObjectAnimator ofPropertyValuesHolder (Object target,
PropertyValuesHolder... values)
The API doc describes this constructor for ObjectAnimator as:
"This variant should be used when animating several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows you to associate a set of animation values with a property name."
Example:
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder transX = PropertyValuesHolder.ofKeyframe("translationX", kf0, kf1, kf2);
PropertyValuesHolder transY = PropertyValuesHolder.ofKeyframe("translationY", kf0, kf1, kf2);
ObjectAnimator transAnim = ObjectAnimator.ofPropertyValuesHolder(view2animate, transX, transY);
transAnim.setDuration(5000);
transAnim.start();
The example above moves view2animate in both x and y axis at the same time.
The 3rd way is to use ViewPropertyAnimator.

Cocos2d-X: CCDrawNode draw circle/custom shape

I am using CCDrawNode to create mask type effect (not exactly mask). Everything works well but there is one problem that CCDrawNode only draws square and i want to draw it with custom texture/sprite. Is there any solution to it.
Below is my code of using CCDrawNode
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
CCLayer *layer = CCLayer::create();
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
layer->addChild(pSprite, 0);
addChild(layer);
//this is the layer that we want to "cut"
CCLayer* layer1 = CCLayerColor::create(ccc4(122, 144, 0, 255), visibleSize.width, visibleSize.height);
this->setTouchEnabled(true);
//we need to create a ccnode, which will be a stencil for ccclipingnode, draw node is a good choice for that
stencil = CCDrawNode::create();
//CCClipingNode show the intersection of stencil and theirs children
CCClippingNode *cliper = CCClippingNode::create(stencil);
cliper->setInverted(true);
cliper->addChild(layer1);
addChild(cliper);
return true;
}
void HelloWorld::ccTouchesMoved(CCSet* touches, CCEvent* event)
{
CCTouch* touch = (CCTouch*)touches->anyObject();
// get start & end location
CCPoint start = touch->getLocationInView();
CCPoint end = touch->getPreviousLocationInView();
// get corrected location
start = CCDirector::sharedDirector()->convertToGL(start);
end = CCDirector::sharedDirector()->convertToGL(end);
//stencil->drawDot(start, 25, ccc4f(0, 0, 0, 255));
stencil->drawSegment(start, end, 25, ccc4f(0, 0, 0, 255));
}
If you want to draw custom texture you should use CCRenderTexture. In order to draw something you should go smthin like this
myRenderTexture->begin();
mySpriteLoadedWithTexture->visit();
myRenderTexture->end();
Also if you want the drawn lines to be smooth you should draw it in loop so that they are placed in equal distance
float distance = ccpDistance(start, end);
for (int i = 0; i < distance; i++)
{
float difx = end.x - start.x;
float dify = end.y - start.y;
float delta = (float)i / distance;
m_brush->setPosition(CCPoint(start.x + (difx * delta), start.y + (dify * delta)));
m_brush->visit();
}
Hope it helps

Android move object along a path

I have created a path and circle and displayed both of them on screen as follows:
public void onDraw(Canvas canvas){
Path sPath = new Path();
sPath.moveTo(100, 100);
sPath.lineTo(300, 100);
sPath.lineTo(300, 300);
sPath.lineTo(100,300);
sPath.lineTo(100,100);
sPath.close();
Paint ballPaint = new Paint();
ballPaint.setColor(Color.GREEN);
Paint pathPaint = new Paint();
pathPaint.setColor(Color.BLUE);
canvas.drawPath(sPath, ballPaint);
canvas.drawCircle(100,100,20,pathPaint);
}
i would like to have the circle move along the path, how can i do this?
Here are the animators I use:
Purpose: Move View "view" along Path "path"
v21+:
ValueAnimator pathAnimator = ObjectAnimator.ofFloat(view, "x", "y", path)
v11+:
ValueAnimator pathAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
float[] point = new float[2];
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = animation.getAnimatedFraction();
PathMeasure pathMeasure = new PathMeasure(path, true);
pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null);
view.setX(point[0]);
view.setY(point[1]);
}
});
Yes, it's possible to move image along path. I will provide simple solution to show the principle. The following code will animate the circle along the path.
int iCurStep = 0;// current animation step
#Override
protected void onDraw(Canvas canvas) {
PathMeasure pm = new PathMeasure(sPath, false);
float fSegmentLen = pm.getLength() / 20;//we'll get 20 points from path to animate the circle
float afP[] = {0f, 0f};
if (iCurStep <= 20) {
pm.getPosTan(fSegmentLen * iCurStep, afP, null);
canvas.drawCircle(afP[0],afP[1],20,pathPaint);
iCurStep++;
invalidate();
} else {
iCurStep = 0;
};
};
v21+: this creates a quadratic bezier curve on a path and animates myView along it.
final Path path = new Path();
path.quadTo(controlX, controlY, finalX, finalY);
ObjectAnimator.ofFloat(myView, View.X, View.Y, path).start();
You would need to move your circle a little bit each frame towards the next waypoint and detect once it gets there, then start moving toward the next. There is no built in system that I know of.
The right way to do this is with ContraintLayout and then add a keyframe between the points on the path you want to animate, as described here: https://medium.com/google-developers/defining-motion-paths-in-motionlayout-6095b874d37.

Android, move bitmap along a path?

I would like to know if it's possible to select coordinates from a path to draw a bitmap over time, for example, I have an image of a sun, and I would like to move it, over time, along an arc path.
Is there some way to define a path like this and then move along it, so that I don't have to calculate it mathematically?
Thanks.
Yes, it's possible to move image along path. I will provide simple solution to show the principle. The following code will move and rotate your image. If you don't need rotation remove the TANGENT_MATRIX_FLAG flag.
import android.graphics.*;
//somewhere global
int iCurStep = 0;// current step
//don't forget to initialize
Path pathMoveAlong = new Path();
private static Bitmap bmImage = null;
#Override
protected void onDraw(Canvas canvas) {
Matrix mxTransform = new Matrix();
PathMeasure pm = new PathMeasure(pathMoveAlong, false);
float fSegmentLen = pm.getLength() / 20;//20 animation steps
if (iCurStep <= 20) {
pm.getMatrix(fSegmentLen * iCurStep, mxTransform,
PathMeasure.POSITION_MATRIX_FLAG + PathMeasure.TANGENT_MATRIX_FLAG);
canvas.drawBitmap(bmImage, mxTransform, null);
iCurStep++;
invalidate();
} else {
iCurStep = 0;
};
};
Here are the animators I use:
Purpose: Move View "view" along Path "path"
v21+:
ValueAnimator pathAnimator = ObjectAnimator.ofFloat(view, "x", "y", path)
v11+:
ValueAnimator pathAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
pathAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
float[] point = new float[2];
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float val = animation.getAnimatedFraction();
PathMeasure pathMeasure = new PathMeasure(path, true);
pathMeasure.getPosTan(pathMeasure.getLength() * val, point, null);
view.setX(point[0]);
view.setY(point[1]);
}
});
Similar requirement to: https://stackoverflow.com/a/30254715/4344057
I'm thinking of one solution:
_
/ \
If your arc has this kind of shape (meaning less than half a circle and positioned horizontaly) then you could iterate the x value and for that x get the y that's on the path. Then move your bitmap to that position.

Categories

Resources