Si necesitas implementar un botón de "me gusta", "amor" o "favorito", este tutorial es para ti. Exploraremos algunas soluciones de código abierto que pueden permitirte lograrlo. Lo haremos paso a paso utilizando ejemplos de código.

(a). LikeButton

LikeButton es una librería que permite crear un botón con efectos de animación similares al corazón de Twitter cuando te gusta algo.

Aquí está la demostración:

Android LikeButton

Paso 1: Instalación

**Repositorio

Comienza registrando el Repositorio:

Añade esto en tu archivo build.gradle raíz (no en tu archivo build.gradle del módulo):

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

Dependencia

A continuación, añade la siguiente declaración de implementación en el archivo build.gradle de tu módulo:

    implementation 'com.github.jd-alexander:LikeButton:0.2.3'

Por defecto obtendrás el botón de corazón con el código anterior.

Paso 2: Añadir al Layout

El siguiente paso es añadir el LikeButton en tu layout xml:

<com.like.LikeButton
            app:icon_type="heart"
            app:icon_size="25dp"
            android:id="@+id/star_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

Explora los atributos que puedes usar con esta librería a continuación:

<com.like.LikeButton
app:icon_type="Star"
app:circle_start_color="@color/colorPrimary"
app:like_drawable="@drawable/thumb_on"
app:unlike_drawable="@drawable/thumb_off"
app:dots_primary_color="@color/colorAccent"
app:dots_secondary_color="@color/colorPrimary"
app:circle_end_color="@color/colorAccent"
app:icon_size="25dp"
app:liked="true"
app:anim_scale_factor="2"
app:is_enabled="false"
/>

Así es como puedes, por ejemplo, establecer un tipo de recurso de icono de forma declarativa:

app:icon_type="heart"

Paso 3: Escuchar eventos

Ahora puede adjuntar mediante programación un manejador de eventos al botón en su código, y escuchar los eventos "like/unlike":

likeButton.setOnLikeListener(new OnLikeListener() {
            @Override
            public void liked(LikeButton likeButton) {

            }

            @Override
            public void unLiked(LikeButton likeButton) {

            }
        });

También puedes programar un tipo de icono como el siguiente:

likeButton.setIcon(IconType.Star);

Y para establecer el tamaño del icono:

likeButton.setIconSizePx(40);
likeButton.setIconSizeDp(20);

Referencia

A continuación se muestra el enlace de descarga para el proyecto de ejemplo.

Número Enlace
1. Leer más
2. Descargar
3. Seguir al autor del código

(b). MaterialFavoriteButton

Un botón animado de favorito/estrella/me gusta para android.

Aquí está la demostración de esta biblioteca:

MaterialFavoriteButton

Veamos cómo usar este paquete.

Paso 1: Instalarlo

Empieza por instalarlo. Añade la siguiente declaración de implementación en tu módulo build.gradle:

implementation 'com.github.ivbaranov:materialfavoritebutton:0.1.5'

Luego sincroniza para descargarlo.

Paso 2: Añadir al Layout

Lo siguiente que tienes que hacer es añadir MaterialFavoriteButton a tu layout xml:

<com.github.ivbaranov.mfb.MaterialFavoriteButton
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

Aquí están los atributos xml que se pueden utilizar:

app:mfb_state="false"                            // default button state
app:mfb_animate_favorite="true"                  // to animate favoriting
app:mfb_animate_unfavorite="false"               // to animate unfavoriting
app:mfb_padding="12"                             // image padding
app:mfb_favorite_image="@drawable/ic_fav"        // custom favorite resource
app:mfb_not_favorite_image="@drawable/ic_not_fav"// custom not favorite resource
app:mfb_rotation_duration="400"                  // rotation duration
app:mfb_rotation_angle="360"                     // rotation angle
app:mfb_bounce_duration="300"                    // bounce duration
app:mfb_color="black"                            // black or white default resources (enum)
app:mfb_type="star"                              // star or heart shapes (enum)
app:mfb_size="48"                                // button size

Paso 3: Escribir el código

A continuación, puede escribir su código ya sea en kotlin o java. Por ejemplo, puedes crear programáticamente el MaterialFavoriteButton sin añadirlo al layout. Lo haces de la siguiente manera

MaterialFavoriteButton favorite = new MaterialFavoriteButton.Builder(this)
        .create();

Para obtener el estado de favorito/no favorito o me gusta/no me gusta, adjuntas un manejador de eventos de la siguiente manera:

favorite.setOnFavoriteChangeListener(
        new MaterialFavoriteButton.OnFavoriteChangeListener() {
          @Override
          public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean favorite) {
            //
          }
        });

Uso en RecyclerView

Para evitar que se desencadene la animación mientras se vuelve a renderizar la vista del elemento, asegúrate de establecer el estado del botón favorito en onBindViewHolder sin animación:

favoriteButton.setFavorite(isFavorite(data.get(position)));

Ejemplo completo

Veamos ahora un ejemplo completo escrito en Java. Empieza instalando la librería como habíamos comentado antes.

Luego se crea un diseño xml:

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="none"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main"
    tools:context=".MainActivity">

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

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/card_margin">

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="@dimen/text_padding"
            android:text="Basic"
            android:textAppearance="@style/TextAppearance.AppCompat.Title" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="@dimen/text_padding"
            android:text="@string/ipsum_1" />

        <com.github.ivbaranov.mfb.MaterialFavoriteButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

      </LinearLayout>

    </android.support.v7.widget.CardView>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/card_margin">

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="@dimen/text_padding"
            android:text="Nice"
            android:textAppearance="@style/TextAppearance.AppCompat.Title" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="@dimen/text_padding"
            android:text="@string/ipsum_en_1914_1" />

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

          <TextView
              android:id="@+id/counter_text"
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_centerVertical="true"
              android:layout_marginLeft="@dimen/starred_margin"
              android:text="@string/starred" />

          <TextView
              android:id="@+id/counter_value"
              android:layout_width="wrap_content"
              android:layout_height="match_parent"
              android:layout_centerVertical="true"
              android:layout_toRightOf="@+id/counter_text"
              android:layout_marginLeft="@dimen/counter_value_margin" />

          <com.github.ivbaranov.mfb.MaterialFavoriteButton
              android:id="@+id/favorite_nice"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignParentRight="true"
              app:mfb_rotation_duration="400"
              app:mfb_rotation_angle="216"
              app:mfb_bounce_duration="700" />

        </RelativeLayout>

      </LinearLayout>

    </android.support.v7.widget.CardView>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/card_margin">

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

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

          <TextView
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:padding="@dimen/text_padding"
              android:text="Custom"
              android:textAppearance="@style/TextAppearance.AppCompat.Title" />

          <com.github.ivbaranov.mfb.MaterialFavoriteButton
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_alignParentRight="true"
              app:mfb_rotation_duration="700"
              app:mfb_rotation_angle="360"
              app:mfb_favorite_image="@drawable/ic_event_available_black_24dp"
              app:mfb_not_favorite_image="@drawable/ic_event_busy_black_24dp"
              app:mfb_animate_unfavorite="true"
              app:mfb_bounce_duration="0" />

        </RelativeLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="@dimen/text_padding"
            android:text="@string/ipsum_2" />

      </LinearLayout>

    </android.support.v7.widget.CardView>

  </LinearLayout>

</ScrollView>

Luego reemplaza el código de su MainActivity con lo siguiente:

MainActivity.java

public class MainActivity extends AppCompatActivity {
  private TextView niceCounter;
  private int niceCounterValue = 37;

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

    //in the toolbar
    MaterialFavoriteButton toolbarFavorite = new MaterialFavoriteButton.Builder(this) //
        .favorite(true)
        .color(MaterialFavoriteButton.STYLE_WHITE)
        .type(MaterialFavoriteButton.STYLE_HEART)
        .rotationDuration(400)
        .create();
    toolbar.addView(toolbarFavorite);
    toolbarFavorite.setOnFavoriteChangeListener(
        new MaterialFavoriteButton.OnFavoriteChangeListener() {
          @Override
          public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean favorite) {
            Snackbar.make(buttonView, getString(R.string.toolbar_favorite_snack) + favorite,
                Snackbar.LENGTH_SHORT).show();
          }
        });

    //nice cardview
    niceCounter = (TextView) findViewById(R.id.counter_value);
    niceCounter.setText(String.valueOf(niceCounterValue));
    MaterialFavoriteButton materialFavoriteButtonNice =
        (MaterialFavoriteButton) findViewById(R.id.favorite_nice);
    materialFavoriteButtonNice.setFavorite(true, false);
    materialFavoriteButtonNice.setOnFavoriteChangeListener(
        new MaterialFavoriteButton.OnFavoriteChangeListener() {
          @Override
          public void onFavoriteChanged(MaterialFavoriteButton buttonView, boolean favorite) {
            if (favorite) {
              niceCounterValue++;
            } else {
              niceCounterValue--;
            }
          }
        });
    materialFavoriteButtonNice.setOnFavoriteAnimationEndListener(
        new MaterialFavoriteButton.OnFavoriteAnimationEndListener() {
          @Override
          public void onAnimationEnd(MaterialFavoriteButton buttonView, boolean favorite) {
            niceCounter.setText(String.valueOf(niceCounterValue));
          }
        });
  }

  @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);
  }
}

Referencia

Encuentre el enlace de descarga a continuación:

Número Enlace
1. Leer más
2. Descargar
3. Seguir al autor del código

(c). SparkButton

Librería de Android para crear botones con animación tipo corazón de Twitter.

Esta librería soporta la API 14+.

Aquí hay una demostración de su uso:

SparkButton Ejemplo Android](https://github.com/varunest/SparkButton/raw/master/art/showcase.gif)

Para usarlo:

Paso 1: Instalarlo

Primero tienes que instalarla. Como está alojado en jitpack, registra jitpack de la siguiente manera en tu archivo build.gradle de nivel raíz:

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

Luego añade tu declaración de implementación:

    implementation 'com.github.varunest:sparkbutton:1.0.6'

Sincronízalo para descargarlo.

Paso 2: Añadir al Layout

Ahora tienes que añadir SparkButton a tu layout xml:

        <com.varunest.sparkbutton.SparkButton
            android:id="@+id/spark_button"
            android:layout_width="40dp"
            android:layout_height="40dp"
            app:sparkbutton_activeImage="@drawable/active_image"
            app:sparkbutton_inActiveImage="@drawable/inactive_image"
            app:sparkbutton_iconSize="40dp"
            app:sparkbutton_primaryColor="@color/primary_color"
            app:sparkbutton_secondaryColor="@color/secondary_color" />

Aquí están los atributos aplicables:

<attr name="sparkbutton_iconSize" format="dimension|reference" />
<attr name="sparkbutton_activeImage" format="reference" />
<attr name="sparkbutton_disabledImage" format="reference" />
<attr name="sparkbutton_primaryColor" format="reference" />
<attr name="sparkbutton_secondaryColor" format="reference" />
<attr name="sparkbutton_pressOnTouch" format="boolean" />
<attr name="sparkbutton_animationSpeed" format="float" />

Paso 3: Escribir el código

También puedes crear el botón mediante programación y establecer los atributos a través de java:

            SparkButton button  = new SparkButtonBuilder(context)
                .setActiveImage(R.drawable.active_image)
                .setInActiveImage(R.drawable.inactive_image)
                .setDisabledImage(R.drawable.disabled_image)
                .setImageSizePx(getResources().getDimensionPixelOffset(R.dimen.button_size))
                .setPrimaryColor(ContextCompat.getColor(context, R.color.primary_color))
                .setSecondaryColor(ContextCompat.getColor(context, R.color.secondary_color))
                .build();

Referencia

Encuentre el enlace de descarga a continuación:

Número Enlace
1. Leer más
2. Descargar
3. Siga al autor del código

Que tenga un buen día.