Learning about andriod development: Image flip so easy,
Hello, everyone. I'm akira. Let's take a look at the following short video.
SO what does this mean? It's too common for everyone to go to or out of the mall. He's just a revolving door.
It's so easy for us to move in with the revolving door and then come out again. It's even easier to have only one flip door.
In some movies we watch, there are some similar customs or secrets that use such a door. However, the latter is simpler, but the two doors are simplified into one.
But the results are the same. Of course, what we are talking about today is not a question of course. Since we are mobile developers, we will naturally think about how this thing works on us.
How does the andriod client implement it?
Today, we will introduce a very simple way to use a normal animation to implement it. Some people may be surprised because it involves some 3D effects, so you can use 2D.
Can an animation be implemented? The answer is yes. Because we know that our naked eyes are prone to deception, a simple example is what magic means.
Close-to-scene magic we all know that magic is false, but we can see it clearly with the naked eye. It is really amazing that it disappears into the magician's hands. Then we can come to a conclusion that sometimes the naked eye is unreliable, but it will bring me a feeling of deception. The following example is the best proof.
What kind of pillar is round or square? Have you seen it or have three or two pillars?
Okay, since the naked eye can be spoofed, we can make a pseudo 3D effect. The core class is the scaling animation in our animation.
We learned from experience that when people look at objects in the distance, they will find that objects become smaller and objects become larger when they look closer.
This is in line with our ScaleAnimation features
Use ScaleAnimation below
The most vague aspect of ScaleAnimation is its structure to explain the problem.
/** * Constructor to use when building a ScaleAnimation from code * * @param fromX Horizontal scaling factor to apply at the start of the * animation * @param toX Horizontal scaling factor to apply at the end of the animation * @param fromY Vertical scaling factor to apply at the start of the * animation * @param toY Vertical scaling factor to apply at the end of the animation * @param pivotXType Specifies how pivotXValue should be interpreted. One of * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or * Animation.RELATIVE_TO_PARENT. * @param pivotXValue The X coordinate of the point about which the object * is being scaled, specified as an absolute number where 0 is the * left edge. (This point remains fixed while the object changes * size.) This value can either be an absolute number if pivotXType * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. * @param pivotYType Specifies how pivotYValue should be interpreted. One of * Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or * Animation.RELATIVE_TO_PARENT. * @param pivotYValue The Y coordinate of the point about which the object * is being scaled, specified as an absolute number where 0 is the * top edge. (This point remains fixed while the object changes * size.) This value can either be an absolute number if pivotYType * is ABSOLUTE, or a percentage (where 1.0 is 100%) otherwise. */ public ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) { mResources = null; mFromX = fromX; mToX = toX; mFromY = fromY; mToY = toY; mPivotXValue = pivotXValue; mPivotXType = pivotXType; mPivotYValue = pivotYValue; mPivotYType = pivotYType; initializePivotPoint(); }
This is the construction Source Code of ScaleAnimation. The above annotations clearly illustrate what our parameters represent.
First, the first fromX is obviously from the back to the addition of X to the X coordinate.
Okay, this understanding of the next two Y is naturally not difficult. So what are the next four?
We found that the rest of Naso correspond to a type and value, and it is an X and Y, which is obviously the x and Y axes.
Looking at the above annotations, we can easily find that the X and Y here are actually scaled based on what we often call the reference object OK.
It's easy. Next we just need to know what type it is.
Back to the trajectory of the analysis problem, since we know the scaling animation, it is not difficult to know that the rotation is actually an indent and expansion process.
However, the indentation and expansion here are switched to deceive our naked eyes and let us think that it is rotating.
View the layout code.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!--<TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" />--> <ImageView android:id="@+id/img_ad" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg" android:scaleType="matrix" /></LinearLayout>
It's a simple figure. Here you will find that I have specified a matrix. This is because we want to make it have an image effect during conversion.
The Code is as follows:
Public class MainActivity extends Activity {private ImageView mImageView; private ScaleAnimation out; private ScaleAnimation in; private boolean ismirror = false; // whether the image is private MediaPlayer mPlayer; String path = ""; // playback path @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); initView (); if (mPlayer = null) mPlayer = New MediaPlayer (); // MediaPlayer mp = MediaPlayer. create (this, R. m); // you do not need to try {mPlayer. setDataSource (path); mPlayer. setAudioStreamType (AudioManager. STREAM_MUSIC); mPlayer. prepare (); mPlayer. setOnPreparedListener (new MediaPlayer. onPreparedListener () {@ Override public void onPrepared (MediaPlayer mp) {mPlayer. start () ;}}) ;}catch (IOException e) {e. printStackTrace ();}/**/mImageView. setOnCl IckListener (new View. OnClickListener () {@ Override public void onClick (View v) {Matrix matrix = new Matrix (); if (! Ismirror) {out = new ScaleAnimation (-1.0f, 1.0f, 1.0f, 1.0f, Animation. RELATIVE_TO_PARENT, 0.5f, Animation. RELATIVE_TO_PARENT, 0.5f); out. setDuration (1200); out. setFillAfter (true); mImageView. startAnimation (out); matrix. postScale (-1, 1); //-1 indicates taking the opposite number, and 1 indicates retaining the unchanged matrix. postTranslate (mImageView. getMeasuredWidth (), 0); mImageView. setImageMatrix (matrix); ismirror = true;} else {in = new ScaleAnimation (1.0f,-1.0f, 1.0f, 1.0f, Animation. RELATIVE_TO_PARENT, 0.5f, Animation. RELATIVE_TO_PARENT, 0.5f); in. setDuration (1200); in. setFillAfter (true); mImageView. startAnimation (in); // Matrix matrix = mImageView. getMatrix (); // Matrix matrix = new Matrix (); matrix. postScale (1, 1); //-1 indicates taking the opposite number, and 1 indicates retaining the unchanged matrix. postTranslate (-mImageView. getMeasuredWidth (), 0); mImageView. setImageMatrix (matrix); ismirror = false ;}});} private void initView () {mImageView = (ImageView) findViewById (R. id. img_ad) ;}@ Override protected void onDestroy () {mPlayer. stop (); mPlayer = null; super. onDestroy ();}}
The code here is relatively simple. The core is to use a Boolean value in two animations to determine whether an image is used.
Then, use postScale to reverse set the mirror effect and then pan it. Here post is used, and set and pre cannot be used, unless you are the first time.
Another thing to note is postTranslate, where the translation is a shift, not a coordinate. OK. If you want to use music
You can use mediaplayer to play a video. I didn't do it here.
PS: If you want to play the video, it is best to use the service to do exactly what is in line with the mvc idea.
The effect is as follows:
One of the following situations is that we may encounter the same situation that we really want to perform a magic trick, that is, the transfer and transfer are different.
In fact, this feature also utilizes scaleanimation, but we have changed the parameter.
Layout is still a chart
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:background="@drawable/bg" /></RelativeLayout>
The code is not the previous Code
The Code is as follows:
Public class MainActivity extends Activity {private ImageView mImageViwe; private ScaleAnimation inTwo; private ScaleAnimation outTwo; private boolean zero = true; // is it the first @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); init (); mImageViwe. setOnClickListener (new MyOnImageCilckListener ();} private void init () {mImageViwe = (ImageView) findViewById (R. id. image); inTwo = new ScaleAnimation (1.0f, 0.0f, 1.0f, 1.0f, Animation. RELATIVE_TO_PARENT, 0.5f, Animation. RELATIVE_TO_PARENT, 0.5f); inTwo. setDuration (1, 500); inTwo. setFillAfter (true); outTwo = new ScaleAnimation (0.0f, 1.0f, 1.0f, 1.0f, Animation. RELATIVE_TO_PARENT, 0.5f, Animation. RELATIVE_TO_PARENT, 0.5f); outTwo. setDuration (1, 500); outTwo. setFillAfter (true);}/* @ Override public boolean onCreateOptionsMenu (Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater (). inflate (R. menu. menu_main, menu); return true;} @ Override public boolean onOptionsItemSelected (MenuItem item) {// Handle action bar item clicks here. the action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest. xml. int id = item. getItemId (); // noinspection SimplifiableIfStatement if (id = R. id. action_settings) {return true;} return super. onOptionsItemSelected (item);} */class MyOnImageCilckListener implements View. onClickListener {@ Override public void onClick (View v) {if (zero) {mImageViwe. startAnimation (inTwo); inTwo. setAnimationListener (new Animation. animationListener () {@ Override public void onAnimationStart (Animation animation) {}@ Override public void onAnimationEnd (Animation animation) {mImageViwe. startAnimation (outTwo); Bitmap map2 = BitmapFactory. decodeResource (getResources (), R. drawable. bg2); mImageViwe. setImageBitmap (map2);} @ Override public void onAnimationRepeat (Animation animation) {}}); zero = false;} else {mImageViwe. startAnimation (inTwo); inTwo. setAnimationListener (new Animation. animationListener () {@ Override public void onAnimationStart (Animation animation) {}@ Override public void onAnimationEnd (Animation animation) {mImageViwe. startAnimation (outTwo); Bitmap map = BitmapFactory. decodeResource (getResources (), R. drawable. bg); mImageViwe. setImageBitmap (map) ;}@ Override public void onAnimationRepeat (Animation animation) {}}); zero = true ;}}}}
You define the cycle. If you do not define the cycle, your animation will not have any effect.
Here we still use a Boolean value to judge whether we find that the rotation is around the center, so when the rotation is gone, that is, before the animation ends, we need to display the next one.
The animationListener listener is used to display a new
Okay, so we can do the second one.
View the effect
Haha, buying a demo and sending a free version has become a weakness for domestic host players, but I am still very much looking forward to FF's new work.
In this issue, we will be here for the next period.