Multi-Selection Animation in Android

Multi selection can be tricky on mobile. Default solutions, where you have a list with check boxes at the right behave bad when the list is getting real big and gets more functionality like filtering.

Suppose when creating your own playlists it can be confusing to understand which songs have already been added without switching between several screens or endlessly scrolling through a list of selected songs.
And the situation may get even worse if we decide to apply filters. In this case, the list of compositions may change once we’ve applied a filter, but the compositions you’ve already selected may not be displayed at all. Vitally decided to solve this problem with yalantis.com concept for multiselection.


In this little experiment, the screen is divided into two parts, so user can always see and manage what he selected without leaving current view. As for filtering or else, it applies only for main left list.

Implementing the component

The animation’s logic seems straightforward, yet it has a few catches.
The component has a ViewPager with two RecyclerViews. We can make a ViewPager page narrower than the screen by overriding the getPageWidth method in the ViewPager adapter and returning a floating number between 0 and 1.
A ViewPager has two pages, each with the RecyclerView. Unselected items are on the left list. Selected items are on the right one.
For instance, if you click an unselected item, a few things will happen:
  1. The clicked item is deleted from the unselected items list and added to the container that holds both lists.
  2. Item position in the selected items list is determined. (The unselected list always has its items sorted alphabetically. The selected list has its items in the order they were selected)
  3. A hidden item is added to the selected items list.
  4. The translation animation is run for the clicked item.
  5. The clicked item is deleted and the hidden item in the selected list is shown.

How to use MultiSelect

Here are 5 simple steps to follow if you want to use this multiselect component in your project.

1. First, add this to your root build.gradle:

allprojects {
  repositories {
   ...
   maven { url "https://jitpack.io" }
  }
}
And then add this to your module build.gradle:
 dependencies {
   compile 'com.github.yalantis:multi-selection:v0.1' }

2. Then create a ViewHolder:

class ViewHolder extends RecyclerView.ViewHolder {
   TextView name;
   TextView comment;
   ImageView avatar;

   public ViewHolder(View view) {
       super(view);
       name = (TextView) view.findViewById(R.id.name);
       comment = (TextView) view.findViewById(R.id.comment);
       avatar = (ImageView) view.findViewById(R.id.yal_ms_avatar);
   }

   public static void bind(ViewHolder viewHolder, Contact contact) {
       viewHolder.name.setText(contact.getName());
       viewHolder.avatar.setImageURI(contact.getPhotoUri());
       viewHolder.comment.setText(String.valueOf(contact.getTimesContacted()));
   }
}

Take note of the static bind method. It’s useful to have it in here because that way you can use the same viewholder in both adapters.

Download Source Code


3. Next, create two adapters for unselected and selected items. 

The first one should extend BaseLeftAdapter; the second, BaseRightAdapter:
public class LeftAdapter extends BaseLeftAdapter<Contact, ViewHolder>{
   private final Callback callback;

   public LeftAdapter(Callback callback) {
       super(Contact.class);
       this.callback = callback;
   }

   @Override
   public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       View view =  LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
       return new ViewHolder(view);
   }

   @Override
   public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
       super.onBindViewHolder(holder, position);

       ViewHolder.bind(holder, getItemAt(position));

       holder.itemView.setOnClickListener(view -> {
           // ...
           callback.onClick(holder.getAdapterPosition());
           // ...
       });

   }

}
Notice that you should call super constructor with the model class you use in the adapters.
The adapter for selected items is very similar:
public class RightAdapter extends BaseRightAdapter<Contact, ViewHolder> {

   private final Callback callback;

   public RightAdapter(Callback callback) {
       this.callback = callback;
   }

   @Override
   public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
       View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false);
       return new ViewHolder(view);
   }

   @Override
   public void onBindViewHolder(@NotNull final ViewHolder holder, int position) {
       super.onBindViewHolder(holder, position);

       ViewHolder.bind(holder, getItemAt(position));

       holder.itemView.setOnClickListener(view -> {
           // ...
           callback.onClick(holder.getAdapterPosition());
           // ...
       });
   }
}
Adapters need to extend different base classes because unselected items are sorted, but selected items stay in the order they were previously selected.

4. Finally, call the builder:

MultiSelectBuilder<Contact> builder = new MultiSelectBuilder<>(Contac
       .withContext(this)
       .mountOn((ViewGroup) findViewById(R.id.mount_point))
       .withSidebarWidth(46 + 8 * 2); // ImageView width with paddings
You’ll then need to:
  • Pass the context.
  • Pass the view (usually FrameLayout) that you want the component to be mounted on.
  • Specify the sidebar width in dp (shown in the image below).

how-we-build-a-multiselection-component-for-android-application

5. Last but not least, set the adapters:

LeftAdapter leftAdapter = new LeftAdapter(position -> mMultiSelect.select(position));
RightAdapter rightAdapter = new RightAdapter(position -> mMultiSelect.deselect(position));

leftAdapter.addAll(contacts);

builder.withLeftAdapter(leftAdapter)
       .withRightAdapter(rightAdapter);
Now all you need to do is call builder.build(), which returns the MultiSelect<T> instance.

Thats it.

Search Filter Animation in Android

Today i am telling you how to implementing Search Filter Animation in Kotlin for Quora Meets LinkedIn.

How we implemented Search Filter animation

We had to make it scalable so it can be independent from the filter items count. We chose the combination of ScrollView and HorizontalScrollView as a solution to this problem.
The ScrollView contains an expanded filter view that places items in such a way that they take all the possible width of the parent view. The HorizontalScrollView has a collapsed filter view where filter items are placed one after another.

Dowload this library

Add to your root build.gradle:

allprojects {
    repositories {
    ...
    maven { url "https://jitpack.io" }
    }
}

Add the dependency:

dependencies {
    compile 'com.github.yalantis:searchfilter:v1.0.1'
}

How to use this library

search filter animation in android

Firstly you need to place Filter above your RecyclerView in the layout file
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:elevation="4dp"
            android:paddingRight="16dp">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <android.support.v7.widget.AppCompatImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_centerVertical="true"
                    android:src="@drawable/ic_alarm"
                    android:tint="@android:color/white" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="Questions"
                    android:textColor="@android:color/white"
                    android:textSize="20sp" />

                <android.support.v7.widget.AppCompatImageView
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:src="@drawable/ic_search"
                    android:tint="@android:color/white" />

            </RelativeLayout>

        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#E4E6E3"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/container_height"
            tools:listitem="@layout/item_list" />

        <com.yalantis.filter.widget.Filter
            android:id="@+id/filter"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </FrameLayout>
</android.support.design.widget.CoordinatorLayout>
After that you need to create a class that extends FilterAdapter and to pass your model class as a generic. Here you can easily customize the appearance of filter items.
For the sample app I created Tag model to represent the category of a question in the conversation.
class Adapter extends FilterAdapter<Tag> {

        Adapter(@NotNull List<? extends Tag> items) {
            super(items);
        }

        @NotNull
        @Override
        public FilterItem createView(int position, Tag item) {
            FilterItem filterItem = new FilterItem(ExampleActivity.this);

            filterItem.setStrokeColor(mColors[0]);
            filterItem.setTextColor(mColors[0]);
            filterItem.setCheckedTextColor(ContextCompat.getColor(ExampleActivity.this, android.R.color.white));
            filterItem.setColor(ContextCompat.getColor(ExampleActivity.this, android.R.color.white));
            filterItem.setCheckedColor(mColors[position]);
            filterItem.setText(item.getText());
            filterItem.deselect();

            return filterItem;
        }
    }
To receive all the events from the Filter such as selection or deselection of a filter item it's necessary to add a FilterListener with the same model class passed as a generic
private FilterListener<Tag> mListener = new FilterListener<Tag>() {

        @Override
        public void onFiltersSelected(@NotNull ArrayList<Tag> filters) {

        }

        @Override
        public void onNothingSelected() {

        }

        @Override
        public void onFilterSelected(Tag item) {

        }

        @Override
        public void onFilterDeselected(Tag item) {

        }

    };
Basically Filter setup looks like that
mFilter = (Filter<Tag>) findViewById(R.id.filter);
 mFilter.setAdapter(new Adapter(getTags()));
 mFilter.setListener(this);

 //the text to show when there's no selected items
 mFilter.setNoSelectedItemText(getString(R.string.str_all_selected));
 mFilter.build();
For more usage examples please review sample app

Let us know!

We’d be really happy if you sent us links to your projects where you use our component.

Liquid Pour Loading Animation Android Example

Today i am giving you a great animation tutorial for loading progress with liquid pour effect and in previous article you can learn to create your custom loading progress bar by using Road runner library. But here you'll teach another cool animation effect for your loading animation.
You can also check : Circular Fillable Loaders Android Library
Just look at the example below :

Cool animation for all project : Kick Out the Wrong Password Android Animation

In xml layout file

 <com.gospelware.liquidbutton.LiquidButton
       android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:clickable="true" />

Uses startPour() to start the animation.

LiquidButton liquidButton = (LiquidButton) findViewById(R.id.button);
      liquidButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
            LiquidButton btn = (LiquidButton) v;
            btn.startPour();
      }
      });

Set fillAfter using setFillAfter(), befault as not fill after

liquidButton.setFillAfter(true);

Set autoPlay using setAutoPlay(), default as not palying automatically

liquidButton.setAutoPlay(true);

Register PourFinishListener to the widget

It will send a callback onPourFinish() when the animation completed, and onProgressUpdate() when new progress is updated;
liquidButton.setPourFinishListener(new LiquidButton.PourFinishListener() {

           @Override
            public void onPourFinish() {
                  Toast.makeText(MainActivity.this, "Finish", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onProgressUpdate(float progress) {
                  textView.setText(String.format("%.2f", progress * 100) + "%");
            }          
      });

How to update and finish the animation?

You'll able to uses changeProgress() to alternate the progress of the liquid level. (You need AutoPlay turn Off to be able to do that.) Progress are measure in float, where 1f = 100%;
liquidButton.changeProgress(progress);
Note :
By default the widget starts a finish animation when the progress is 1f, but you can also uses finishPour to start the finish Animation.
liquidButton.finishPour();

How to?

Gradle
dependencies {    
            compile 'com.gospelware.liquidbutton:liquidButtonLib:1.1.4'
      }

Hope you like this tutorial. If it is then please give some time to share with your friends.

Top 25 Android Libraries you can try in 2017 - Part 1

This is a list of 25 best Android libraries released in January and February 2017. All of these are worth trying out — they are not in ranked order.


Let’s get started!

1. Lottie

This is a library that parses Adobe After Effects animations exported as JSON with Bodymovin (After Effects plugin for exporting animations to SVG/Canvas/HTML + JavaScript) and renders them natively on mobile.
There is also an example app available in the Google Play Store.
The more than 7,500 Github users who starred this library can not be wrong!



lottie-android - Render After Effects animations natively on Android and iOS

2. Toasty

This is a library for creating customized Toasts. As the author described the lib, it is:
“The usual Toast, but with steroids.”
You can find screenshots and the link to the library below.



Toasty - The usual Toast, but with steroids 💪

3. StyleableToast

This is another library for Toasts customization. It adds:
“variety of styling options that gives your app and user experience that little extra unique feeling! Style your toast either by code or in styles.xml!”



StyleableToast - A library that takes the standard Android toast to the next level with a variety of styling options…

4. Store

Store is a library for Async Data Loading and Caching. According to the documentation:
“Store is a class that simplifies fetching, parsing, storage, and retrieval of data in your application. A Store is similar to the Repository pattern while exposing a Reactive API built with RxJava that adheres to a unidirectional data flow.”
The documentation is really comprehensive and the lib is for sure worth trying. You can check many flows such as data requests, caching and parsing.
Store - Android Library for Async Data Loading and Caching

5. PreviewSeekBar

If you use Google Play Movies, you have probably noticed this great animated SeekBar with a preview of the movie. It turned out that Rúben Sousa implemented that as an open-source library. The gif below gives a good flavor of its functionalities. If your app is for instance a movie player, you should definitely try it!



PreviewSeekBar - A SeekBar suited for showing a preview of something. As seen in Google Play Movies.

6. Chuck

If you use OkHttp, this is the library that helps intercept and persist all HTTP requests and responses inside your application. It also provides a UI for inspecting their content.


chuck - An in-app HTTP inspector for Android OkHttp clients

7. CoordinatorTabLayout

CoordinatorTabLayout is a custom composite control that quickly implements the combination of TabLayout and CoordinatorLayout.
You can check how it works on the gif below:


CoordinatorTabLayout - Combination of TabLayout and CoordinatorLayout./TabLayout/CoordinatorLayout

8. boxing

Boxing is a multimedia selector and by using it you can:
do a selection of your images (single or multiple images)
preview and crop images.
It also supports gifs, video selection, image compression and custom UI as shown in the screenshot below:



boxing - Android multi-media selector based on MVP mode.

9. excelPanel

This is a two-dimensional RecyclerView. It can not only load historical data, but also load future data.


excelPanel - An Android's two-dimensional RecyclerView. Not only can load historical data, but also can load future…

10. Horizontal Calendar

Another implementation for RecyclerView is dedicated to show Material horizontal Calendar View.


HorizontalCalendar - A material horizontal calendar view for Android based on RecyclerView
Next >>

Top 25 Android Libraries you can try in 2017 - Part 2

Hey friends in my previous article i am list of top 10 android libraries which you can try in 2017 and the second part of this series is there.


Hope you like it too.

11. CameraFragment

CameraFragment is an implementation of a Fragment which allows you to easily integrate a camera functionality to your app. According to its README:
“CameraFragment previews directly the camera view, and provides an easy API to capture or manage the device. You can setup your own layout and control the camera using CameraFragment.”


CameraFragment - A simple easy-to-integrate Camera Fragment for Android

12. AwesomeBar

This is another great implementation from Florent Champigny. It is new approach to a design of a top bar (which we know from ActionBar/Toolbar implementation), in conjunction with DrawerLayout, inspired by Gmail Mobile from Weekz. You can check, how it works below:


AwesomeBar - Just beautiful

13. ArcNavigationView

This is an implementation of NavigationView from Android Design Support Library which introduces curved edges.



ArcNavigationView - Another approach to create NavigationDrawer with Material concepts

14. ShimmerRecyclerView

It is a custom RecyclerView implementation with shimmer views to indicate that views are loading. The RecyclerView has also a built-in adapter, to control the shimmer appearance.


Contribute to ShimmerRecyclerView development by creating an account on GitHub.

15. Android-SwitchIcon

“A Google launcher-style implementation of switch (enable/disable) icon.”
This library extends AppCompatImageView and allows you to set any icon (vector or image), to SwitchIconView using app:srcCompat attribute.


Android-SwitchIcon - Google launcher-style implementation of switch (enable/disable) icon

16. CounterFab

This library is a FloatingActionButton subclass that shows a counter badge in the top right corner. You can download a demo app from Google Play.


CounterFab - A FloatingActionButton subclass that shows a counter badge on right top corner

17. FadingTextView

This library allows you to make a TextView change its content automatically every few seconds.

FadingTextView - A textview that changes its content automatically every few seconds

18. Bridge

“Bridge is a simple but powerful HTTP networking library for Android. It features a Fluent chainable API, powered by Java/Android’s URLConnection classes for maximum compatibility and speed.”
This library has a really comprehensive documentation and is definitely worth checking out.
bridge - A simple but powerful HTTP networking library for Android. It features a Fluent chainable API, powered by Java…

19. Ason

It is the second library from Aidan Follestad. Its main idea is to simplify an interaction with JSON. The library:
“also makes (de)serialization painless.”
The documentation is also pretty good. You can check it out here:
ason - JSON in Java made easy!

20. ObjectBox

I assume that majority of you knows greenrobot. If not, they developed GreenDAO and EventBus. Now, this is time for a new database for objects focused on performance. As greenrobot claims,
“Performance is the number one reason why we created ObjectBox. Previously, we created greenDAO, the fastest Object/Relational Mapper (ORM) for Android and SQLite. Since its first release in 2011, we gained a lot of insight into object persistence — and the performance limitations imposed by SQLite. We realized that in order to improve performance on mobile significantly, we needed to go to the core and build a database designed for objects.”

You can read more about it here. Please take into consideration that ObjectBox is currently in beta (version 0.9.7 ).


ObjectBox is a superfast mobile database for objects

<<Prev                                    Next>>

Top 25 Android Libraries you can try in 2017 - Part 3

Hey geekers in my previous article i am list of top 20 android libraries which you can try in 2017 and the second part of this series is there.



Hope you like it too.

21. FlowLayout

This library:
“allows child views flow to next row when there is not enough space.
The spacing between child views can be calculated by the FlowLayout so that the views are evenly placed.”

Please note that this is still in its early stages of development.


FlowLayout - A flow layout for Android with auto-spacing.

22. Unofficial Google Actions Java SDK

This is a polish accent from Mirek Stanek. Because of the fact that the official Google Actions SDK is written in Node.js, he introduced his unofficial version written natively in Java. According to the README:
“Google Actions Java SDK is built based on official Node.js library, but it’s not a mirror copy of it. The goal is to make it fully compatible with Conversational Protocol of Assistant Platform.”

Google-Actions-Java-SDK - Unofficial Google Actions Java SDK - for Android engineers and all Java lovers

23. Wearable Reply

On 9th of February 2017 Google released a new Android Wear 2.0.
Luke Klinker found a missing API and released the library for this OS. It:
“allows for quick and easy text input, whether that is from your voice, a keyboard, or canned responses. The missing API is now available!”



wearable-reply - Simplify text input for Android Wear 2.0, by voice, keyboard, or canned response.

24. Shortbread

This is a library:
“generates app shortcuts for Activities and methods annotated with @Shortcut. No need to touch the manifest, create XML files or use the shortcut manager. Just annotate the code that you want the shortcut to call.”
Currently, it’s at version 1.0.0.

shortbread - Android library that generates app shortcuts from Shortcut annotations

25. Material About

This library helps you to prepare an About Me screen to introduce you to your users.



MaterialAbout - It's a material-design about screen to use on your Android apps. A developer profile and application…

That’s it. I hope you enjoyed my list. If you know any great library, which was released in January or February this year and I didn’t mention about it, please let me know in the comments.

Kick Out the Wrong Password Android Animation

Hello friends now a day many of android applications are making and the successful measure of popular application is their UI, Clean up and animation effect too. In my previous article  i show you how to use beautiful form submit animation. Just look at that tutorial.

In this tutorial you are gonna see kick out the wrong password animation for Android application. Most of android application need authentication and find wrong password if any intruder want to access.

For fast android development : How to Use JRebel for Android

We use that form but not in traditional way just look at below demo and tell me about it.


Cool isn't it...
If you think it is cool and want to implement this then dive in the code now.

What we do in our animation ?

Firstly it showing normal form with CircularImageView and single EditText.
When you entered wrong password and click on submit button then it lock image move and kick the wrong password and remain blank the password and fadeout a red message "Wrong password" and after some time it gone and EditText is blank again.

Play and edit with Full source codeHungerMoji - Android Notification Game 

In layout here we create password layout(layout_password.xml) separately from normal form for avoid confusion and then include that layout in our main layout(activity_main.xml).

layout_password.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?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="wrap_content"
    android:layout_marginTop="20dp"
    android:background="@drawable/bg_edit_text"
    android:orientation="horizontal">
 
 
    <ImageView
        android:id="@+id/ivLock"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:padding="10dp"
        android:src="@drawable/ic_locked_padlock" />

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/etPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_edit_text"
            android:inputType="textPassword"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingTop="5dp"
            android:text="Hello"
            android:textSize="30sp" />

       <LinearLayout
            android:id="@+id/llParent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="15dp"
            android:gravity="center"
            android:orientation="horizontal"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingTop="5dp">

            <ImageView
                android:id="@+id/ivDummy"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_dot"
                android:visibility="gone" />

            <EditText
                android:id="@+id/etDummy"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:focusable="true"
                android:focusableInTouchMode="true"></EditText>
        </LinearLayout>
    </FrameLayout>
</LinearLayout>

What we done above in layout ?


  • Line 10-15 : It is a padlock ImageView which will move and take a role to kick out the wrong password from EditText.
  • Line 33-57 : This linear layout will holds all dots generated during animation. Padding, margin of this linear layout must be in match with Edit text.
  • Line 44-49 : This is just to simulate position of dots. Visibility of this image view must be in GONE state.
  • Line 51-56 : This is used to remove focus of password edittext.

Now we implement animation in our layout from activity.
Main_Activity.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.CycleInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;



public class MainActivity extends AppCompatActivity {

    EditText etPassword, etDummy;
    Button btnLogin;
    private LinearLayout llParent;
    private ImageView ivLock;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        etPassword = (EditText) findViewById(R.id.etPassword);
        etDummy = (EditText) findViewById(R.id.etDummy);
        ivLock = (ImageView) findViewById(R.id.ivLock);
        llParent = (LinearLayout) findViewById(R.id.llParent);
        btnLogin = (Button) findViewById(R.id.btnLogin);

        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //  Hide cursor/focus from edit text after click
                removeFocus();

                String password = etPassword.getText().toString();
                etPassword.setText("");

                validatePassword(password);
            }
        });
    }

    private void validatePassword(String password) {
        //  TODO Perform password validation here and if failed then proceed with below

        int passLength = password.length();
        playHangingAnimation(ivLock);

        //  Generate number of dots (imageview) similar to length of input password
        for (int i = 0; i < passLength; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setImageResource(R.drawable.ic_dot);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT);
            params.setMargins(3, 0, 3, 0);
            imageView.setLayoutParams(params);
            llParent.addView(imageView);

            //  Play animation for each and every dots separately
            playKickOutAnimation(imageView, i);
        }
    }

    private void playKickOutAnimation(final View view, int i) {
        //  Parameters are startPositionX,endPositionX, startPositionY, endPositionY
        //  Intentionally changed position of X at runtime based on i(index of dot) to give elastic effect
        //  Play around these numbers and let community know if any combination is giving better result :)
        Animation animation = new TranslateAnimation(-20 + i * 5, 400, 0, 0);

        //  Intentionally changed duration at runtime based on i(index of dot) to give elastic effect
        animation.setDuration(700 + i * 20);

        //  To give kick out effect. Read about all Inter polator here - http://cogitolearning.co.uk/?p=1078
        animation.setInterpolator(new AnticipateInterpolator());

        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //  Remove dots from screen once animation has been stopped
                llParent.removeView(view);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        view.startAnimation(animation);
    }

    private void playHangingAnimation(View v) {
        int pivot = Animation.RELATIVE_TO_SELF;
        //  Parameter defines how many times the cycle should happen
        CycleInterpolator interpolator = new CycleInterpolator(2.5f);
        //  Parameters are fromDegree,toDegree,positionXType(from self in this case),positionX,positionYType,positionY
        //  Play around these values to get to know the behaviour more closely
        RotateAnimation animation = new RotateAnimation(0, 20, pivot, 0.47f, pivot, 0.05f);
        animation.setStartOffset(100);
        animation.setDuration(900);
        animation.setRepeatCount(0);// Animation.INFINITE
        animation.setInterpolator(interpolator);
        v.startAnimation(animation);
    }

    private void removeFocus() {
        etPassword.clearFocus();
        etDummy.requestFocus();
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(etDummy.getApplicationWindowToken(), 0);
    }
}

What we do in activity above ?


  • Firstly we got value of EditText and call validatePassword(password) function in onCreate from line 36-48 and definition of that is start from line 50-69 in which we perform password validation here and if failed then proceed with below and call playHangingAnimation(ivLock) whose play a role to animate padlock from line 103-115.
  • Generate number of dots (imageview) similar to length of input password  and then play animation for each and every dots separately by calling playKickOutAnimation(imageView, i) from line 71-101.
  • And finally we removeFocus from Edit text from line 117-122.

Download Source code

Hope you like this tutorial please comment below and like my Facebook page.



Form Submit Animation Android Example

Hello friends, I hope you doing well in development and my blog helped when you face any problem. Today i am sharing a cool animation tutorial for Android which you can use in any application and they boost the look of your application.



You must read this : Android Developers Get Wrong in Material Design

In old way when you make a form in Android with submit button it stores the data with boring loading bar. But after this tutorial you can make cool animation for this. Just take a look in below image :

Cool isn't it. If you liked then just dive in the code now.

See the difference : Google ProgressBar V/s FAB ProgressBar

Download Source Code

In this project we use ButterKnife for Field and method binding with Android views.

Now start with simple layout with three EditText with floating action button

<LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="First edit text" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Second edit text" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="Third edit text" />
        </LinearLayout>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@drawable/ic_send_white_24dp" />
And now we want to add some animation in our simple layout so firstly we add all layout in FrameLayout and now our layout look likes
<FrameLayout
        android:id="@+id/inputs_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/background_light"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="First edit text" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Second edit text" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="Third edit text" />
        </LinearLayout>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@drawable/ic_send_white_24dp" />

    </FrameLayout>
Now at last we use some more layouts to achieve our aim like io.codetail.widget.RevealFrameLayout and final layout xml would be

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.jaouan.sendinganimationexample.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <RelativeLayout
        android:id="@+id/sky_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/sky">

        <FrameLayout
            android:id="@+id/plane_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentEnd="true">

            <ImageView
                android:id="@+id/plane"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/plane_margin"
                android:rotation="180"
                android:src="@drawable/ic_send_white_24dp" />
        </FrameLayout>

        <io.codetail.widget.RevealFrameLayout
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_centerInParent="true">

            <RelativeLayout
                android:id="@+id/sent_layout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/rounded">

                <ImageView
                    android:id="@+id/check"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    android:padding="20dp"
                    android:src="@drawable/ic_check_white_24dp" />
            </RelativeLayout>
        </io.codetail.widget.RevealFrameLayout>

    </RelativeLayout>

    <FrameLayout
        android:id="@+id/inputs_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/background_light"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="First edit text" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Second edit text" />

            <EditText
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="Third edit text" />
        </LinearLayout>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            android:src="@drawable/ic_send_white_24dp" />

    </FrameLayout>


</android.support.design.widget.CoordinatorLayout>
Now we add animation in our layout by Activity file. Here we'll firstly click on floating button by which all the input layout hide and rotate the fab and then flying fab button animation will start with full screen cover and at last restore the input layout.

We just start with binding the ButterKnife library in onCreate function.

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
        ButterKnife.bind(this);
    }

Now make function for onClick on fab button

@OnClick(R.id.fab)
    void send() {
        // - Prepare views visibility.
        mCheckImageView.setVisibility(View.INVISIBLE);
        mSentLayout.setVisibility(View.INVISIBLE);

        // - Rotate fab.
        final RotateAnimation rotateAnimation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
        rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        rotateAnimation.setDuration(280);
        mFab.startAnimation(rotateAnimation);

        // - Hide inputs layout.
        final Animator circularReveal = ViewAnimationUtils.createCircularReveal(mInputsLayout, (int) (mFab.getX() + mFab.getWidth() / 2), (int) (mFab.getY() + mFab.getHeight() / 2), mInputsLayout.getHeight(), 0);
        circularReveal.setDuration(250);
        circularReveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // - Update views visibility.
                mInputsLayout.setVisibility(View.INVISIBLE);

                // - Fly away.
                flyAway();
            }
        });
        circularReveal.start();

    }

Implement fly button animation

private void flyAway() {
        // - Combine rotation and translation animations.
        final RotateAnimation rotateAnimation = new RotateAnimation(0, 180);
        rotateAnimation.setDuration(1000);
        mPlaneImageView.startAnimation(rotateAnimation);
        Revealator.reveal(mSentLayout)
                .from(mPlaneLayout)
                .withTranslateDuration(1000)
                .withCurvedTranslation(new PointF(-1200, 0))
                .withRevealDuration(200)
                .withHideFromViewAtTranslateInterpolatedTime(.5f)
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {

                        // - Display checked icon.
                        final ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
                        scaleAnimation.setInterpolator(new BounceInterpolator());
                        scaleAnimation.setDuration(500);
                        scaleAnimation.setAnimationListener(new AnimationListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animation animation) {
                                mInputsLayout.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {

                                        // - Restore inputs layout.
                                        retoreInputsLayout();

                                    }
                                }, 1000);
                            }
                        });
                        mCheckImageView.startAnimation(scaleAnimation);
                        mCheckImageView.setVisibility(View.VISIBLE);

                    }
                }).start();
    }

After animation done we just restore our input fields

private void retoreInputsLayout() {
        mInputsLayout.postDelayed(new Runnable() {
            @Override
            public void run() {

                final Animator circularReveal = ViewAnimationUtils.createCircularReveal(mInputsLayout, (int) (mFab.getX() + mFab.getWidth() / 2), (int) (mFab.getY() + mFab.getHeight() / 2), 0, mInputsLayout.getHeight());
                circularReveal.setDuration(250);
                circularReveal.start();

                mInputsLayout.setVisibility(View.VISIBLE);
            }
        }, 1000);
    }

Final Main_Activity.java

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.graphics.PointF;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.BounceInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;

import com.jaouan.revealator.Revealator;
import com.jaouan.revealator.animations.AnimationListenerAdapter;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.fab)
    View mFab;

    @BindView(R.id.plane)
    View mPlaneImageView;

    @BindView(R.id.plane_layout)
    View mPlaneLayout;

    @BindView(R.id.inputs_layout)
    View mInputsLayout;

    @BindView(R.id.sky_layout)
    View mSkyLayout;

    @BindView(R.id.sent_layout)
    View mSentLayout;

    @BindView(R.id.check)
    View mCheckImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
        ButterKnife.bind(this);
    }

    /**
     * Send something.
     */
    @OnClick(R.id.fab)
    void send() {
        // - Prepare views visibility.
        mCheckImageView.setVisibility(View.INVISIBLE);
        mSentLayout.setVisibility(View.INVISIBLE);

        // - Rotate fab.
        final RotateAnimation rotateAnimation = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
        rotateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
        rotateAnimation.setDuration(280);
        mFab.startAnimation(rotateAnimation);

        // - Hide inputs layout.
        final Animator circularReveal = ViewAnimationUtils.createCircularReveal(mInputsLayout, (int) (mFab.getX() + mFab.getWidth() / 2), (int) (mFab.getY() + mFab.getHeight() / 2), mInputsLayout.getHeight(), 0);
        circularReveal.setDuration(250);
        circularReveal.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // - Update views visibility.
                mInputsLayout.setVisibility(View.INVISIBLE);

                // - Fly away.
                flyAway();
            }
        });
        circularReveal.start();

    }

    /**
     * Starts fly animation.
     */
    private void flyAway() {
        // - Combine rotation and translation animations.
        final RotateAnimation rotateAnimation = new RotateAnimation(0, 180);
        rotateAnimation.setDuration(1000);
        mPlaneImageView.startAnimation(rotateAnimation);
        Revealator.reveal(mSentLayout)
                .from(mPlaneLayout)
                .withTranslateDuration(1000)
                .withCurvedTranslation(new PointF(-1200, 0))
                .withRevealDuration(200)
                .withHideFromViewAtTranslateInterpolatedTime(.5f)
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {

                        // - Display checked icon.
                        final ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f);
                        scaleAnimation.setInterpolator(new BounceInterpolator());
                        scaleAnimation.setDuration(500);
                        scaleAnimation.setAnimationListener(new AnimationListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animation animation) {
                                mInputsLayout.postDelayed(new Runnable() {
                                    @Override
                                    public void run() {

                                        // - Restore inputs layout.
                                        retoreInputsLayout();

                                    }
                                }, 1000);
                            }
                        });
                        mCheckImageView.startAnimation(scaleAnimation);
                        mCheckImageView.setVisibility(View.VISIBLE);

                    }
                }).start();
    }

    /**
     * Restores inputs layout.
     */
    private void retoreInputsLayout() {
        mInputsLayout.postDelayed(new Runnable() {
            @Override
            public void run() {

                final Animator circularReveal = ViewAnimationUtils.createCircularReveal(mInputsLayout, (int) (mFab.getX() + mFab.getWidth() / 2), (int) (mFab.getY() + mFab.getHeight() / 2), 0, mInputsLayout.getHeight());
                circularReveal.setDuration(250);
                circularReveal.start();

                mInputsLayout.setVisibility(View.VISIBLE);
            }
        }, 1000);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
}

Thats it. Hope you like this tutorial and if you've any issues or problem or suggestion then please comment in below and like my Facebook page.