Good day to all. I want to devote this post to a subject of fragments for Android. On Habré there are already translations and some articles that mention how to start working with fragments under Android. For example, the article
Fragments API in Android 3.0 . It contains a description of what fragments are and in which version of Android they are available, so those who have not yet reached it can, if they wish, become familiar, I will not retell this in my post. Therefore, I will immediately get down to business.
Beginning of work
Let me just say briefly that fragments are user UI components that can be used by the Activity class to display user data, but their life cycle does not depend on it. The functionality that fragments are endowed with has a wider functionality for working with them than the Activity, so their use for developers is of no small importance if they want their application to have a more modern user interface according to current standards.
We now turn to the essence of the post. Google developers fragments were endowed, in my opinion, with excellent support for animating the display of the fragment itself. This will be discussed further. I was looking for posts on Habr on this topic, but I did not find anything, so now I will share my knowledge.
')
Create a project
Let's create a small project. I created a project for my Samsung Nexus S, there I have a version of Android 4.1.2, which I actually used (Api Level 16). I called the project itself FragmentsAnimationTest.
For the demonstration, we will need the main activation and its layout, a couple of fragments, each also with its layout and another pair of xml files for the animation itself, which I will discuss later.
The application will look as follows: one of the fragments will be displayed on the screen, switching between them will be carried out using a normal button, and, accordingly, the switching of fragments will be accompanied by animation effects.
First, we place the elements of the main activation in the activity_main.xml file:
<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" > <FrameLayout android:id="@+id/fragCont" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" > </FrameLayout> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="SWITCH FRAGMENTS" android:layout_toRightOf="@id/fragCont"/> </RelativeLayout>
From the code, it is clear that the main layout is used - RelativeLayout, which is quite convenient when working with fragments; two standard FrameLayout elements are placed in it - in fact, it will be a container for fragments and a button that will switch fragments between them. So far everything has to be extremely simple.
Further we will be engaged in our fragments. Create markup for them and the classes themselves:
fragment1.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#5A4"> <TextView android:layout_width="200dp" android:layout_height="fill_parent" android:text="fragment 1"/> </LinearLayout>
fragment2.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#A55"> <TextView android:layout_width="200dp" android:layout_height="fill_parent" android:text="fragment 2"/> </LinearLayout>
For both fragments, the code is almost the same; they differ only in the text that will be displayed in the fragment itself to identify it and the background color so that the animation can be clearly seen.
Fragment1.java
public class Fragment1 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_1, null); } }
Fragment2.java
public class Fragment2 extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_2, null); } }
Classes should also be clear if they are familiar with the theme of the fragments. They simply indicate which particular layout will be used when displaying a specific fragment and that's it.
Now we will start the most tasty. Let's work with the main activity class, here is its code:
public class MainActivity extends Activity { private Fragment fragment2; private Fragment fragment1; private FragmentTransaction ft; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fragment1 = new Fragment1(); fragment2 = new Fragment2(); ft = getFragmentManager().beginTransaction(); ft.setCustomAnimations(R.animator.slide_in_left, R.animator.slide_in_right);
Let us analyze what exactly is happening in our activism. First, both fragments are created, which, as already mentioned, will alternately change each other. Next we specify the line ft = getFragmentManager (). BeginTransaction () to get the FragmentTransaction, with which we can interact with our fragments, but this is all in the article I mentioned earlier. Before proceeding to the analysis of the following code, I will make a small digression.
There are two ways to create animations to display fragments:
- The first method is to connect standard animation using the setTransition (int transit) method. In the FragmentTransaction class, there are several pre-defined animations.
- The second method is exactly what interests us in this topic, the implementation of custom animation. Implemented using the setCustomAnimations () method
Now back to the analysis of our code. Let's look at the following line ft.setCustomAnimations (R.animator.slide_in_left, R.animator.slide_in_right), then the animation is connected to all fragments that will be processed before the transaction is completed, to the line ft.commit (). What exactly is happening? Two parameters are passed to setCustomAnimations. The first parameter describes the animation to display the fragment that appears, and the second describes the animation for the fragment that changes, i.e. removed from the device screen. It is important to mention that this method should be called before the fragments appear, otherwise the animation will not be applied.
A couple of stock comments is to try to play around with the pre-defined animation, just uncomment and comment out the previous line - ft.setCustomAnimations (R.animator.slide_in_left, R.animator.slide_in_right), in both cases, although this not necessary.
Let's analyze the activation code to the end and move on to creating the animation itself.
After installing the animation, a fragment is shown, added to the stack and the transaction is completed to display all changes. Then we initialize our button and attach a listener of the button press event to it, inside which there is a code for changing fragments, by pressing the button we start a transaction, activate the animation and change the fragment to the opposite one shown at the moment. The code is simple, so it does not require a deep explanation.
Create an animation
We turn to the main part of our topic. Learn to create the animation itself. The way we create animations here is a bit different from how we used to do this in earlier versions of Android. The implementation is as follows. To get started, you need to create a folder animator in the application resources folder, it will look like this - res / animator /. Here we have to put xml-files that will describe exactly how the animation should play. Put them there:
slide_in_left.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:propertyName="y" android:valueType="floatType" android:valueTo="0" android:valueFrom="-1280" android:duration="1500"/> </set>
and slide_in_right.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:interpolator="@android:anim/accelerate_interpolator" android:propertyName="alpha" android:valueType="floatType" android:valueTo="0" android:duration="300"/> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:propertyName="x" android:valueType="floatType" android:valueTo="1280" android:valueFrom="0" android:duration="1500"/> </set>
Now we will analyze them in detail. The elements of the visual effects themselves are described in the objectAnimator tag, each such tag indicates a description of the new animation effect. Now look at the attributes themselves. The first attribute in the slide_in_left.xml file is an interpolator, it has several values, you can learn more about them in the
Property Animation documentation. Interpolator is responsible for displaying our fragment in a certain way for a certain time. Next we have the propertyName attribute, it indicates with which particular fragment property we’ll change during the animation, in our example, the first is y, and the valueType indicates what type of parameter we have. In the book Pro Android 4, this situation is argued that if you look at the setX () method in the View class, it becomes clear that it takes a value of type float, and the setY () method is also true, hence the value floatType.
Next, there are not unimportant valueFrom and valueTo attributes, they indicate from which value to which value to change the value specified in propertyName, in our first case it is y. If valueFrom is not specified, then the value is equal to the current one. In our case, the valueFrom is equal to -1280, this means that the fragment movement along the y axis will start from -1280, this value was chosen due to the fact that it is outside the screen of the device and the movement will take place until the y value becomes 0 for the upper left corner of our fragment within 1500 milliseconds. And, finally, the duration - the attribute indicates how long our animated effect will last in milliseconds.
And the last nuance that I want to describe. Looking at any of the animation description files, you can see the set tag, which contains all the animation effects, it serves to combine effects or separate them. The slide_in_right.xml file uses the ordering attribute in the set tag, in our case it has the value together, which means playing effects at the same time, as opposed to it there is a value sequentially that requires sequential display of effects in the animation, which is very convenient in some cases.
Actually that's all. The slide_in_right.xml file provides an example of how you can use other properties for animating, such as the alpha channel. I hope this article is useful to those who care what its application will look like.
As you understand, dear habrayuser, screenshots can not display the result of the work.
The literature and sources used to write the post were mentioned during the article itself.