I want to implement the Telegram like image zoom in and out animation in my app. Look at their source code I see the class ClippingImageView animate this effect by using a property animator. The problem is when I try applying this to my app my view getLeft() and getTop() was not at (0, 0). So setTranslationX() and setTranslationY() get the wrong number because animationValues was calculate at (0, 0).
Is there a way I can position the View at (0, 0) with the actual image content take up another part of the screen, like the top right corner?
EDIT
This is what I've tried so far, apparently this is just a part of Telegram source that I cloned to my app.
animationValues store the starting and ending value of the properties.
animationValues[0][0] = animatingImageView.getScaleX();
animationValues[0][1] = animatingImageView.getScaleY();
animationValues[0][2] = animatingImageView.getTranslationX();
animationValues[0][3] = animatingImageView.getTranslationY();
animationValues[0][4] = clipHorizontal * object.scale;
animationValues[0][5] = clipTop * object.scale;
animationValues[0][6] = clipBottom * object.scale;
animationValues[0][7] = animatingImageView.getRadius();
animationValues[1][0] = scale;
animationValues[1][1] = scale;
animationValues[1][2] = xPos;
animationValues[1][3] = yPos;
animationValues[1][4] = 0;
animationValues[1][5] = 0;
animationValues[1][6] = 0;
animationValues[1][7] = 0;
Then in ClippingImageView.java
public void setAnimationProgress(float progress) {
animationProgress = progress;
setScaleX(animationValues[0][0] + (animationValues[1][0] - animationValues[0][0]) * animationProgress);
setScaleY(animationValues[0][1] + (animationValues[1][1] - animationValues[0][1]) * animationProgress);
setTranslationX(animationValues[0][2] + (animationValues[1][2] - animationValues[0][2]) * animationProgress);
setTranslationY(animationValues[0][3] + (animationValues[1][3] - animationValues[0][3]) * animationProgress);
setClipHorizontal((int) (animationValues[0][4] + (animationValues[1][4] - animationValues[0][4]) * animationProgress));
setClipTop((int) (animationValues[0][5] + (animationValues[1][5] - animationValues[0][5]) * animationProgress));
setClipBottom((int) (animationValues[0][6] + (animationValues[1][6] - animationValues[0][6]) * animationProgress));
setRadius((int) (animationValues[0][7] + (animationValues[1][7] - animationValues[0][7]) * animationProgress));
invalidate();
}
I also notice that when I log the animatingImageView.getMeasuredWidth() and animatingImageView.getMeasuredHeight() they all give me 0. Is this just a dummy view for animation purpose?
I have set up a game where Actor fireflies randomly fly across the screen, while glowing on and off — and a user can drag them into a mason jar. Pretty happy I've got this working, but I'd like to add a bit more detail. I'd like to add a two-step animation so that it looks like their wings are flapping.
I know how to do this with the Animation class, making use of TextureAtlas and TextureRegion. But that was prior to me heading in this Drag n Drop direction.
My issue, I think, is that I'm using skins, and they might not play nice with Animations.
///////////////////
Portions of my code.
///////////////////
Some of the items I declare up top:
private TextureAtlas textureAtlas;
private Texture texture;
private TextureRegion[] regions = new TextureRegion[3];
private Animation ffFlapping;
Setting up my TextureAtlas:
textureAtlas = new TextureAtlas(Gdx.files.internal("Player Animation/player_animation.png.atlas"));
texture = new Texture(Gdx.files.internal("Player Animation/player_animation.png.png"));
Setting up the skin:
final Skin skin = new Skin();
skin.addRegions(textureAtlas);
Doing the animation:
TextureRegion[] ffAnimation = new TextureRegion[2];
ffAnimation[0] = (textureAtlas.findRegion("firefly-0"));
ffAnimation[1] = (textureAtlas.findRegion("firefly-1"));
ffFlapping = new Animation(0.01f, ffAnimation);
For loop to create all my fireflies:
// ********************************************
// iterate through the number of fireflies
// we want to draw out using fireflyCount
// ********************************************
for (int fireflyIndex = 0; fireflyIndex < fireflyCount; fireflyIndex++) {
// YELLOW FIREFLY HERE
String fireflyName = "firefly" + fireflyIndex;
// if I replace ffFlapping below with object, I get no errors,
// but also no animation
skin.add(fireflyName, ffFlapping);
final Firefly ff = new Firefly(skin, fireflyName);
System.out.println("Fireflies objects:" + fireflyIndex);
// Not sure this affected the color, but it starts the alpha at 0
ff.setColor(150, 150, 150, 0);
ff.setOrigin(ff.getWidth()/2, ff.getHeight()/2);
stage.addActor(ff);
// This was set up in the attempt to continue movement if user misses target
final MoveToAction actionRight = new MoveToAction();
final MoveToAction actionLeft = new MoveToAction();
// setting up right and left targets, with a random Y position
float toRight = Gdx.graphics.getWidth() + 60;
float toLeft = (Gdx.graphics.getWidth() -Gdx.graphics.getWidth())-60f;
// sets up speed of glow, and the random time firefly is off, and also on
float glow = MathUtils.random(.5f, 1f);
float delayRandomOff = MathUtils.random(2.3f, 4.5f);
float delayRandomOn = MathUtils.random(.5f, .9f);
// sets up first variable to randomly choose between toRight and toLeft
// assigns direction to that value
float randomDirection = MathUtils.random.nextBoolean() ? toRight : toLeft;
float direction = randomDirection;
SequenceAction sequence = new SequenceAction();
AlphaAction aa = new AlphaAction();
Action alphaStartOn = Actions.delay(delayRandomOn, Actions.fadeOut(glow));
Action alphaStartOff = Actions.delay(delayRandomOff, Actions.fadeIn(glow));
// toRight is the x value ... it goes (x, y, duration)
Action startRight = Actions.moveTo(toRight, MathUtils.random(50, Gdx.graphics.getHeight() - 40), MathUtils.random(10f, 45f));
// toLeft is the x value ... it goes (x, y, duration)
// 170 makes sure they don't fly on top of mason jar
Action startLeft = Actions.moveTo(toLeft, MathUtils.random(170, Gdx.graphics.getHeight() - 40), MathUtils.random(10f, 45f));
Action faceOpposite = Actions.rotateBy(180f);
Action faceOpposite2 = Actions.rotateBy(180f);
// THIS ENDLESSLY LOOPS THEM ON THE SCREEN
Action loopRight = Actions.forever(Actions.sequence(faceOpposite, startRight, faceOpposite2, startLeft));
Action loopLeft = Actions.forever(Actions.sequence(startLeft, faceOpposite, startRight, faceOpposite2));
Action loopGlow1 = Actions.forever(Actions.sequence(alphaStartOn, alphaStartOff));
Action loopGlow2 = Actions.forever(Actions.sequence(alphaStartOff, alphaStartOn));
// THIS IS DEFINITELY TRIGGERING THE MOVEMENT
if(direction == toRight) {
ff.addAction(loopRight);
ff.addAction(loopGlow1);
} else {
ff.addAction(loopLeft);
ff.addAction(loopGlow2);
}
// MAKE EACH FIREFLY DRAGGABLE, and SET LARGER SIZE as you drag
dragAndDrop.addSource(new DragAndDrop.Source(ff) {
public DragAndDrop.Payload dragStart (InputEvent event, float x, float y, int pointer) {
DragAndDrop.Payload payload = new DragAndDrop.Payload();
payload.setObject("Firefly captured");
payload.setDragActor(ff);
ff.clearActions();
getActor().setSize(80, 80);
// Firefly freezes on drag, and enlarges ... disappears if dropped in jar
// Does not visually drag with cursor since it was part of animation.
return payload;
}
// IF YOU DON'T DROP FIREFLY ON TARGET, MAKE SURE IT STAYS ON STAGE
// AND GOES BACK TO THE NORMAL SIZE
#Override
public void dragStop(InputEvent event, float x, float y, int pointer, DragAndDrop.Payload payload, DragAndDrop.Target target) {
if(target == null)
stage.addActor(ff);
ff.addAction(actionLeft);
getActor().setSize(50, 50);
}
});
// MAKE EACH FIREFLY DRAGGABLE, and SET LARGER SIZE as you drag
dragAndDrop.addSource(new DragAndDrop.Source(ff) {
public DragAndDrop.Payload dragStart (InputEvent event, float x, float y, int pointer) {
DragAndDrop.Payload payload = new DragAndDrop.Payload();
payload.setObject("Firefly captured");
payload.setDragActor(ff);
ff.clearActions();
getActor().setSize(80, 80);
// Firefly freezes on drag, and enlarges ... disappears if dropped in jar
// Does not visually drag with cursor since it was part of animation.
return payload;
}
// IF YOU DON'T DROP FIREFLY ON TARGET, MAKE SURE IT STAYS ON STAGE
// AND GOES BACK TO THE NORMAL SIZE
#Override
public void dragStop(InputEvent event, float x, float y, int pointer, DragAndDrop.Payload payload, DragAndDrop.Target target) {
if(target == null)
stage.addActor(ff);
ff.addAction(actionLeft);
getActor().setSize(50, 50);
}
});
} // ***** END OF FOR LOOP ***********
And here's my Firefly code:
public class Firefly extends Image {
private float x = MathUtils.random(20, Gdx.graphics.getWidth() -40);
private float y = MathUtils.random(200, Gdx.graphics.getHeight() - 40);
private float width = 70;
private float height = 70;
public Firefly(Skin skin, String drawableName) {
super(skin, drawableName);
this.setBounds(x, y, width, height);
}
} // firefly
The error I'm getting is:
com.badlogic.gdx.utils.GdxRuntimeException: No Drawable, NinePatch, TextureRegion, Texture, or Sprite registered with name: firefly-2
///////////////////////////////
Any tips are very much appreciated.
In the meantime, I'm creating a new feature branch and keeping at it.
My guess is that I need to somehow make my two-step animation into some kind of Drawable.
Thanks!
— Bill
After few hours of trying I'm looking for some hints on how to add snap-scroll mechanism to MPAndroid. Basically I want the 5 visible bars to align so they are fully visible and centered. I now imported the library source code because it looks like there's no other way to change the code in computeScroll (BarLineChartTouchListener).
Edit:
To clarify - I'm showing around 20 bars but chart is zoomed so user can scroll horizontally. What bothers me it is not getting aligned automatically so first visible bar might be clipped in half. I'm looking for snapping effect where it will round the position to the nearest multiplication of the bar width, leaving 5 fully visible bars.
I ended up adding the following function in BarLineChartBase.java. I know it's far from elegant, but seems to do the job. It's limited to targetApi > 11, because of the ValueAnimator. For lower API (which I don't cater for) you might need to have a look at nineoldandroids or some other animation loop technique.
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void alignX() {
int count = this.getValueCount();
int xIndex = this.getLowestVisibleXIndex() + Math.round( (this.getHighestVisibleXIndex() - this.getLowestVisibleXIndex()) / 2.0f );
float xsInView = this.getXAxis().getValues().size() / this.getViewPortHandler().getScaleX();
Transformer mTrans = this.getTransformer(YAxis.AxisDependency.LEFT);
float[] pts = new float[] { xIndex - xsInView / 2f, 0 };
mTrans.pointValuesToPixel(pts);
final Matrix save = new Matrix();
save.set(this.getViewPortHandler().getMatrixTouch());
final float x = pts[0] - this.getViewPortHandler().offsetLeft();
final int frames = 20;
ValueAnimator valueAnimator = new ValueAnimator().ofInt(0, frames);
valueAnimator.setDuration(500);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
int prev = -1;
#Override
public void onAnimationUpdate(ValueAnimator animation) {
if( (int) animation.getAnimatedValue() > prev ) {
save.postTranslate( -x / (float)frames, 0);
BarLineChartBase.this.getViewPortHandler().refresh(save, BarLineChartBase.this, true);
}
prev = (int) animation.getAnimatedValue();
}
});
valueAnimator.start();
}
I trigger it at the end of computeScroll function in BarLineChartTouchListener.
I kept names of variables as I copied code from functions like MoveViewJob, ViewPortHandler etc. Since it's only aligning in x axis - I removed Y axis calculations and used zeros instead. Any optimizations welcome, especially from the author #PhilippJahoda.
In short I want a preview similar to Google Plays, where you can slide up and the top image/video preview fades back and the rest of the view is moved up.
I've got a view that I want to be hiden like the video in this example, the action bar can remain stationary at all times, but I need the bottom part to be dragable.
I can't seem to find out which layout that is, or how it is done, all I managed to find were unrelated such as ViewPager. My current min sdk version is 18, the compile version is 21.
The following is the code I used in the app I am working
You will have to use the OnScrollChanged function in your ScrollView. ActionBar doesn't let you set the opacity , so set a background drawable on the actionbar and you can change its opacity based on the amount of scroll in the scrollview. I have given an example workflow
The function sets gives the appropriate alpha for the view locationImage based on its position WRT window .
this.getScrollY() gives you how much the scrollView has scrolled
public void OnScrollChanged(int l, int t, int oldl, int oldt) {
// Code ...
locationImage.setAlpha(getAlphaForView(locationImageInitialLocation- this.getScrollY()));
}
private float getAlphaForView(int position) {
int diff = 0;
float minAlpha = 0.4f, maxAlpha = 1.f;
float alpha = minAlpha; // min alpha
if (position > screenHeight)
alpha = minAlpha;
else if (position + locationImageHeight < screenHeight)
alpha = maxAlpha;
else {
diff = screenHeight - position;
alpha += ((diff * 1f) / locationImageHeight)* (maxAlpha - minAlpha); // 1f and 0.4f are maximum and min
// alpha
// this will return a number betn 0f and 0.6f
}
// System.out.println(alpha+" "+screenHeight +" "+locationImageInitialLocation+" "+position+" "+diff);
return alpha;
}
You can download an example working sample at https://github.com/ramanadv/fadingActionBar
Credit: CommandSpace
I have implemented the MuPDf in android to open,view,search,setting bookmarks etc for a PDF. Now i want the animation effect of horizontal flip i.e. similar to be like used in the FlipBoard Application in horizontal manner.
I also need to know that how can i highlight the Search Text. I am using Librelio's code
I have gone through the links Like:
Link 1
Please help.
I also need to know that how can i highlight the Search Text.
PageView.java of MuPDF:
private static final int HIGHLIGHT_COLOR = 0x802572AC; //adjust the color
...//some code of PageView.java
public void setPage(int page, PointF size) {
...//code of PageView.setPage(int page, PointF size)
// this is the part where the hightlighting happens
if (!mIsBlank && mSearchBoxes != null) {
paint.setColor(HIGHLIGHT_COLOR);
for (RectF rect : mSearchBoxes)
canvas.drawRect(rect.left*scale, rect.top*scale,
rect.right*scale, rect.bottom*scale, paint);
// you can customize it, e.g.
// int margin = 5
//canvas.drawRect((rect.left - margin) * scale, (rect.top - margin) * scale,
//(rect.right + margin) * scale, (rect.bottom + margin) * scale, paint);
}
}
to start a search, just invoke:
new SearchTask(context, mupdfCore).go("searchText", 1, 0, -1);