问题
I am trying to animate/morph a rectangular view/layout, as all views are rectangular. The user case for this would be: The user long-clicks a view that contains an ImageView or just the main view with a background, a new view would be generated being the size of the screen, then this view would shrink into a circle of a certain size. Possible solution I have found is extending the view class, therefore creating my own view and implementing a custom method, but I am confused on how to animate the view to shrink. Also the view would have to follow the users touch location continuously as it animates/morphs, adding more to the confusion.
回答1:
A quick, not-so-thorough explanation to at least get you thinking in the right direction:
I think the big thing to keep in mind here is that whatever solution you find, the animation is going to be painfully slow unless you perform the transformations entirely within the view's onDraw(Canvas canvas)
method. In other words, avoid anything that requires the view to measure and lay out for every frame of the animation. With this approach, you simply perform a frame transition and call invalidate() on the view to update. Keep in mind that you will lose most of your ability to interact with anything within the view in its circular rendering.
Since there are no shape-transforming animations built into Android, you will probably need to use something like Property Animation to roll it yourself. If you're supporting devices prior to Honeycomb (3.0), you will probably need to bring in the NineOldAndroids library and use its property animation capabilities instead. Essentially, you'll need to animate the values of the corner radius. Best case scenario, you're transforming a square into a circle. Otherwise, you need to do some cropping or dimension transformations as well.
To animate the view, you will first need to obtain a bitmap representing the latest render of that view. You can do that using the following code:
// Creates a bitmap in the size of the view
Bitmap bitmap = Bitmap.createBitmap(myView.getWidth(), myView.getHeight(), Bitmap.Config.RGB_565);
// Creates a new canvas that draws to the bitmap
Canvas canvas = new Canvas(bitmap);
// Draws the contents of the view to the bitmap via the canvas
view.draw(notifyCanvas);
You should only perform this once per animation, and it should occur just prior to performing the animation.
Next, you most likely need to create an empty extended View
simply to hold the animated representation of the view you want to modify.
Implementing the transformation logic in onDraw(Canvas canvas)
(which is done by extending the view as mentioned above), you have access to the Canvas object. Essentially, the Canvas object is the final layer that contains all the "draw" calls that render the view on the screen. Overloading the onDraw
method on your new custom view, you can then use canvas.drawRoundedRect(...)
to draw a rectangle with rounded corners and paint in the bitmap of the view we created in the code above. Within your custom view, you can keep a variable that stores the radius used by drawRoundedRect
. As you animate, you set that radius to be larger and larger until you get a circle (granted, you'll only get a circle if the original shape is a square). This does get pretty complicated, and I've definitely skipped a few steps, but you can see a good example of a rounded view by checking out the RoundedImageView on GitHub. There are lots of good ideas in that library that you could borrow.
Apologies for not pulling together a more complete explanation. It's quite a complex task!
来源:https://stackoverflow.com/questions/20051829/morph-a-retangler-view-into-a-circle