Multiple calls to invalidate with different Rects - android

I am extending my root layout so I can drawBitmap 4 arrows on it, one on each corner of the screen. These arrows will occassionally Blink at the same time.
I am doing this as an optimization to avoid creating 4 additional Views, so I guess it only makes sense if the areas are independently invalidated, because if the whole layout is invalidated & repainted, the performance loss will probably be bigger than the savings, as the root layout contains heavy stuff. I suppose is a good idea, but if anybody thinks it's not, please tell me why.
I tried to call invalidate(Rect) in the same function with each rect:
public MyRootViewGroup extends FrameLayout {
#Override
public void draw (Canvas c) {
super.draw(c); // Draw Viewgroup Children
draw_arrows(); // Paint Arrows over children
invalidate(rect_arrow_left);
invalidate(rect_arrow_right);
invalidate(rect_arrow_bottom);
invalidate(rect_arrow_top);
}
... but unfortunately it seems that only one region gets invalidated with this approach. I need to invalidate the whole layout to make it work.
Question If this FrameLayout contains other children (that get drawn in super.draw() ) but they don't change, will my call to invalidate() cause them all to be repainted? Or Android is somehow smart to detect that only the arrow region has changed despite triggering a full invalidate? Am I optimizing and saving 4 views, or am I breaking Android optimization pipeline?
Regards!

use this code in your next Activity onCreate() method
ImageView imageView1 = (ImageView)findViewById(R.id.imageView1);
ImageView imageView2 = (ImageView)findViewById(R.id.imageView2);
ImageView imageView3 = (ImageView)findViewById(R.id.imageView3);
ImageView imageView4 = (ImageView)findViewById(R.id.imageView4);
Animation animBlank = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.blank);
imageView1.startAnimation(animBlank);
imageView2.startAnimation(animBlank);
imageView3.startAnimation(animBlank);
imageView4.startAnimation(animBlank);
Create an xml file which defines type of animation to perform. This file should be located under anim folder under res directory (res ⇒ anim ⇒ blink.xml). If you don’t have anim folder in your res directory create one.
put following code in blink.xml file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:duration="600"
android:repeatMode="reverse"
android:repeatCount="infinite"/>
</set>

Related

Smooth slider with two (or more) images

How I can reach such behavior with a smooth slider?
I want that first ImageView to increase his width and cover over second ImageView.
I tried three different approaches to this purpose.
First I drew bitmap (two bitmaps combined inside one canvas) inside the canvas of one ImageView. New position generated with ValueAnimation but it gives values with not equals intervals. During rendering the transition do jumps noticeably enough. On a good phone especially.
Second I did my own method for generating sequence numbers without intervals and but occurs another problem: phone cant render new bitmaps a few hundred times per second. If to do intervals jumps occur again.
Then I tried another way: to create two ImageView and first must smooth roll out over the second. But I can't reach the proper effect than the first picture must not stretch (image inside ImageView increased width together) but need a roll-out like on GIF.
Code of my third the attempt:
In fragment
val animation: Animation = AnimationUtils.loadAnimation(ctx, R.anim.scale_right)
imageView.startAnimation(animation)
imageView.visibility = View.VISIBLE
scale_right.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="6000"
android:fromXScale="0"
android:fromYScale="1.0"
android:pivotX="0%"
android:pivotY="0%"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>
What do I need to do?

Translation of image from center to top in android

Hi I have stuck with the problem of creating a splash screen where the image is placed in center_vertical|center horizontal.how to translater over to center_horizontal|top in android.can any one please guide me how to do it.
Use animations to do this, for more information about animating views, you could refer to this link and also this
What you are actually looking for in translating a view from the center to the top of the screen, you could use translation animation using the xml.
1.Create a folder anim in the res folder
2.Add a resource file that describes your translation effect like :
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="50%p" android:fromYDelta="50%p"
android:toXDelta="50%p" android:toYDelta="0%p"
android:duration="1000"
android:fillAfter="true" />
You could experiment with the % values.
3.implement this in code like :
translateAnim= AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.translate_anim);
imageView.startAnimation(translateAnim);
Hope this much of clue suffices!
P.S: You could experiment with fillAfter true or false, so that you could understand their effects better.
This is I think best and easiest approach to achieve animation from center to top:
ivSplashCenter.animate()
.translationY(-((rlContainer.height - (ivSplashCenter.height * 2)) / 2).toFloat())
.setInterpolator(AccelerateInterpolator()).duration = 1500
Here, ivSplashCenter is imageview and rlContainer is my root view of XML
NOTE:
One thing you need to understand here is that I am keeping a space from the top edge of the height of the image by ivSplashCenter.height * 2,
If you don't want any padding/space at the top then you can just use ivSplashCenter.height

Android how to show images with Animation effect

I have 2 images of different color balls. When I press the button I am changing the image on imagebutton from image1(ball1) to image2(ball2). What I want to do is show this image change(ie ball color change with a little animation, effect that it rotates and changes color.
Question: How can I get this effect of rotating ball image1 so that it becomes ball image2 ?
Question: I want to play some sound also along with this effect. How to go about it?
EDIT: basically what I want is: image1 revolves around(180 degree) and becomes image2.
in order to rotate and hide image you will need to use a tween animation framework:http://developer.android.com/guide/topics/resources/animation-resource.html#View. You need to construct animation set that will rotate and reduce alpha of the image.
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
</set>
Then just use ImageView.startAnimation(AnimationUtils.loadAnimation(context, R.anim.your_anim));
This will allow you to fade and rotate the ImageView, while revealing another ImageView below the current one.
If you want to do transition inside of a single ImageView you need to use TransitionDrawable which is a drawable that cross-fades one image to another. Unfortunately it won't allow you rotating content, so you either need to modify it, which is harder.
You could use RotateDrawable as one of the drawables in TransitionDrawable, but I have never tried this.

How to rotate a shape around a central axis

I'm surprised to find so few examples when it comes to Android animation. I have found the animation demos but they provide only a small set of what you might want to achieve.
For my particular case I'm just trying to animate a shape around a central point. I can see from the demo that you can use the following to pass in values:
ObjectAnimator.ofObject(
ballHolder
, "name"
, new XYEvaluator()
, position1, position2, position3, position4, positionEtc);
But how can I pass in all the values for a circle? I'm sure you wouldn't achieve it this way (as in, the example above).
Maybe I should be doing it a different way? Any help would be much appreciated.
try this code and adjust it as you need :
To implement the rotation animation, you can define that animation in XML:
create an animation xml file under /res/anim folder called :rotate_around_center_point.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<rotate android:toDegrees="360"
android:duration="700"
android:pivotX="205"
android:pivotY="180"
android:interpolator="#android:anim/linear_interpolator"/>
</set>
apply the animation to View : lets say it for rotate image :
ImageView animationTarget = (ImageView) this.findViewById(R.id.testImage);
Animation animation = AnimationUtils.loadAnimation(this,
R.anim.rotate_around_center_point); animationTarget.startAnimation(animation);
OR
create the animation dynamically in Java code:
Animation newAnimation = new RotateAnimation(0, 360, 205, 180);
newAnimation.setDuration(700);
animationTarget.startAnimation(newAnimation);
HOPE THIS HELP .

Android -- How to position View off-screen?

I'm trying to animate a simple ImageView in my application and I want it to slide in from the bottom of the screen and come to a resting position where the top 50px of the view is off the top of the screen (e.g. the final position of the ImageView should be -50px in X). I've tried to use the AbsoluteLayout to do this, but this actually cuts off the top 50px of the ImageView such that the top 50px is never rendered. I need to have the top 50px of the ImageView visible/rendered while it's animating and then simply have it come to a rest slightly off-screen. I hope I've explained that well enough.
Here is what I'm currently using as a layout and the slide-in animation (this currently doesn't render the top 50px of the ImageView):
Layout:
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/QuickPlayClipLayout">
<ImageView android:id="#+id/Clip"
android:background="#drawable/clip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_y="-50dp">
</ImageView>
</AbsoluteLayout>
Animation:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p"
android:toYDelta="0"
android:duration="1000"/>
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1000" />
</set>
Instead we can simple give negative values to layout_margin(Top/left/right/bottom)
eg: If you want your view to be off from top of the screen you can specify
android:layout_marginTop="-40dp"
I figured out a solution to this that should be easy to implement. It involves modifying the layout and the Activity inflating the layout... see below:
Activity (QuickPlay.java):
public class QuickPlay extends Activity implements AnimationListener
{
private ImageView myImageView;
private LinearLayout LL;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.quick_play_screen);
myImageView = (ImageView) this.findViewById(R.id.Clip);
LL = (LinearLayout) this.findViewById(R.id.QuickPlayClipLayout);
//finally
Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide_in_quickplay);
anim.setAnimationListener(this);
LL.startAnimation(anim);
}
#Override
public void onAnimationEnd(Animation animation){}
#Override
public void onAnimationRepeat(Animation animation){}
#Override
public void onAnimationStart(Animation animation)
{
// This is the key...
//set the coordinates for the bounds (left, top, right, bottom) based on the offset value (50px) in a resource XML
LL.layout(0, -(int)this.getResources().getDimension(R.dimen.quickplay_offset),
LL.getWidth(), LL.getHeight() + (int)this.getResources().getDimension(R.dimen.quickplay_offset));
}
}
New LinearLayout (CustomLinearLayout.java):
public class CustomLinearLayout extends LinearLayout
{
private Context myContext;
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
myContext = context;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec+((int)myContext.getResources().getDimension(R.dimen.quickplay_offset)));
}
}
Layout (/res/layout/quick_play_screen.xml):
<?xml version="1.0" encoding="utf-8"?>
<com.games.mygame.CustomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/QuickPlayClipLayout">
<ImageView android:id="#+id/Clip"
android:background="#drawable/clip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</ImageView>
</com.games.mygame.CustomLinearLayout>
Resource (/res/values/constants.xml):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="quickplay_offset">50dp</dimen>
</resources>
Animation (/res/anim/slide_in_quickplay.xml):
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p"
android:toYDelta="0"
android:duration="1000"/>
<alpha android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="1000" />
</set>
The program now does exactly what I need it to do. The entire layout starts off screen at the bottom, slides in in 1 sec and comes to a rest where the top of the layout is actually 50px off the top of the screen (i.e. LL.getTop() = -50) and the bottom of the layout is resting at the bottom of the screen (i.e. LL.getBottom() = 530 = 480 + 50).
To position my view offscreen I used the following code:
View myView = /* view you want to position offscreen */
int amountOffscreen = (int)(myView.getWidth() * 0.8); /* or whatever */
boolean offscreen = /* true or false */
int xOffset = (offscreen) ? amountOffscreen : 0;
RelativeLayout.LayoutParams rlParams =
(RelativeLayout.LayoutParams)myView.getLayoutParams();
rlParams.setMargins(-1*xOffset, 0, xOffset, 0);
myView.setLayoutParams(rlParams);
This code will position myView offscreen by amountOffscreen, which in this case puts 80% of the view offscreen leaving only 20% onscreen.
Do not use the layout() method directly - Android will make subsequent calls to invalidate your view for random reasons and only layoutParams are persisted across invalidate calls. If you are curious, check out lines 904 to 912 of this file to see why you have to modify the layoutParams.
This is easy to do if you make to leap to using a Canvas; those support drawing off the screen without any trouble. However, it will be a more complicated to implement. You'd need to implement a custom View and write your own animation in code. Essentially this comes down to simple 2D graphics handling rather than Views using built-in XML animations.
There may be a way to do it with XML, but I'm much more familiar with canvases. A very good place to see how this is handled in code is the Lunar Lander example game that comes with the SDK.
Roughly the steps you'll need to follow are:
Put a custom view in the XML file, using something like <your.package.AnimatingView>, setting its size to fill-parent.
Then define a AnimatingView class, which extends SurfaceView and implements SurfaceHolder.Callback. (This gives you access to the drawing Canvas immediately rather than by using the invalidate() method. This is important because invalidate() only refreshes when the thread is idle, e.g. at the end of the loop. To implement your animation, you need to have it drawing immediately.)
You can then implement a loop which draws your moving image across the screen. The loop needs to start by drawing the whole background (because the canvas doesn't automatically get erased) and then draw the image at its new position based on the time that has passed. For example, if you want your animation to take 1 second to do, then you know that if 200ms have passed, the view should only have moved 200/1000, or 1/5, of the way from its starting position to the final position.
You can see some examples of what I mean in my other answers to animation questions: basic reply about the usefulness of using SurfaceView and and example of the loop to use. Note: the second question was about rotating, and hence some of the difficulties I talked about won't be relevant to you. Good luck!
With android:translationX and android:translationY
<RelativeLayout
android:translationX="-600dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
I had a viewgroup with children and was dragging the view into the screen from the bottom - kind of like a drawer. I then would let go and if the viewgroup top margin were in the top half of the screen I would animate it to the top after the user released the touch.
When this happened the images in the viewgroup's children would get cropped during the animation but would then get shown after the animation.
The problem: viewgroup's height was wrap_content. I solved this by setting the height to a value that stretched off the screen before the animation started.

Categories

Resources