Nâng cao giao diện người dùng cho ứng dụng với hình động

Hình động có thể mang đến các tín hiệu thị giác thông báo cho người dùng về ứng dụng và nâng cao hiểu biết về giao diện của nó. Hình động cũng hữu ích khi tải nội dung hoặc khi màn hình thay đổi trạng thái. Nó cũng mang đến hình ảnh giao diện tuyệt vời cho các ứng dụng.

Hình động không nhất thiết làm cho ứng dụng đẹp hơn nhưng nó gây chú ý của người sử dụng và nâng cao trải nghiệm của họ. Với hàng ngàn ứng dụng có sẵn mỗi ngày, hình động khiến việc sử dụng ứng dụng không còn nhàm chán hoặc khó chịu với người dùng nữa.

Hình động cho ứng dụng

Một số lý do nên kết hợp hình động vào ứng dụng:

  • Để thu hút người dùng - Hình động có thể thu hút người dùng trước khi tải nội dung đầy đủ. Điều này sẽ ngăn người dùng từ bỏ ứng dụng. Gmail là một minh chứng tốt về điều này. Nó sử dụng hình ảnh động trong tính năng pull-to-refresh (kéo xuống để làm mới) và spinner để tải các email mới.
  • Cung cấp phản hồi - Hình động cung cấp các phản hồi trực quan cho thấy một sự kiện hoặc hành động nhất định đã được hoàn thành hoặc để hiển thị các trang web không hoạt động đúng cách. Hình động có thể được sử dụng trong các nút, tab và các thành phần khác thông báo cho người dùng về tình trạng hiện tại của ứng dụng, đặc biệt là trong các ứng dụng thương mại điện tử.
  • Giúp người dùng điều hướng - Điều này đặc biệt hữu ích khi nội dung thay đổi. Ví dụ, thanh cuộn động có thể được sử dụng để hiển thị sự chuyển tiếp giữa các tab và các mục trong trình đơn. Hầu hết các ứng dụng sẽ có màn hình giới thiệu, giới thiệu các tính năng quan trọng nhất của ứng dụng hoặc chỉ đơn giản giải thích cho người dùng về ứng dụng.

Đây là cách bạn có thể thêm một số hình động trong ứng dụng để cải thiện trải nghiệm người dùng.

Tạo một thanh trượt giới thiệu (Introduction Slider)

Thanh trượt này giới thiệu các tính năng khác nhau của ứng dụng. Người dùng có thể điều hướng qua màn hình bằng cách sử dụng các cử chỉ vuốt hoặc bỏ qua phần giới thiệu và đi tới ứng dụng chính.

Thanh trượt giới thiệu sẽ chỉ được hiển thị khi ứng dụng được khởi chạy lần đầu tiên. Các lần khởi chạy tiếp theo sẽ đưa người dùng trực tiếp vào màn hình chính. Bài viết này sẽ hướng dẫn các bạn tạo ba slide trong ứng dụng để hiển thị ba khía cạnh quan trọng nhất của ứng dụng.

Kết quả cuối cùng sẽ giống như sau:

Tạo thanh trượt giới thiệu ứng dụng

Thêm XML này vào một tệp mới có tên slide.xml:

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f64c73">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/shop"
android:textColor="@android:color/white"
android:textSize="30dp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:text="@string/slide_1_title"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="16dp" />
</LinearLayout>
</RelativeLayout>

Thêm code sau vào slide2.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f64c73">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/earn"
android:textColor="@android:color/white"
android:textSize="30dp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:text="@string/slide_1_title"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="16dp" />
</LinearLayout>
</RelativeLayout>

Và thêm những dòng sau trong slide3.xml:

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f64c73">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/redeem"
android:textColor="@android:color/white"
android:textSize="30dp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:text="@string/slide_1_title"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="16dp" />
</LinearLayout>
</RelativeLayout>

Tiếp theo, chúng ta sẽ thiết kế màn hình chào mừng. Tạo một hoạt động khác (activity_welcome.xml) và thêm vào tệp tin XML dòng sau:

 <?xml version="1.0" encoding="utf-8"?>
<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">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/welcomeLayout"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:gravity="center"
android:orientation="horizontal"></LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:alpha=".5"
android:layout_above="@id/welcomeLayout"
android:background="@android:color/white" />
<Button
android:id="@+id/btn_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@null"
android:text="@string/next"
android:textColor="@android:color/white" />
<Button
android:id="@+id/btn_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:background="@null"
android:text="@string/skip"
android:textColor="@android:color/white" />
</RelativeLayout>

Tệp XML chứa một trình xem trang gồm các hành động vuốt và nút, đưa người dùng đến màn hình tiếp theo (hoặc trở lại màn hình trước). Bạn cũng sẽ cần strings.xml cho các định nghĩa như “@string/redeem” v.v…

 <resources>
<string name="app_name">Animation</string>
<string name="title_activity_welcome">Home Screen</string>
<string name="next">NEXT</string>
<string name="skip">SKIP</string>
<string name="start">GOT IT</string>
<string name="shop">SHOP</string>
<string name="earn">EARN</string>
<string name="redeem">REDEEM POINTS</string>
<string name="slide_1_title">SHOP FOR YOUR FAVORITE ITEMS</string>
</resources>

Như đã đề cập ở phần đầu của hướng dẫn này, màn hình chào mừng chỉ được hiển thị khi lần đầu tiên chạy ứng dụng. Để thực hiện việc này, hãy tạo một class có tên PrefManager.java và gọi setFirstTimeLaunch(true) khi ứng dụng được khởi chạy lần đầu tiên.

package com.example.vaatiesther.animation;
import android.content.Context;
import android.content.SharedPreferences;
/**
* Created by vaatiesther on 11/8/17.
*/
public class PrefManager {
SharedPreferences preferences;
SharedPreferences.Editor editor;
Context _context;
int PRIVATE_MODE = 0;

private static final String PREF_NAME = "welcome";
private static final String IS_FIRST_TIME_LAUNCH = "IsFirstTimeLaunch";
public PrefManager(Context context) {
this._context = context;
preferences = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);
editor = preferences.edit();
}

public void setFirstTimeLaunch(boolean isFirstTime) {
editor.putBoolean(IS_FIRST_TIME_LAUNCH, isFirstTime);
editor.commit();
}

public boolean isFirstTimeLaunch() {
return preferences.getBoolean(IS_FIRST_TIME_LAUNCH, true);
}
}

Cuối cùng, thêm code sau vào WelcomeActivity.java:

 package com.example.vaatiesther.animation;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Context;
import android.content.Intent;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
public class WelcomeActivity extends AppCompatActivity {
private ViewPager viewPager;
private PrefManager prefManager;
private MyViewPagerAdapter myViewPagerAdapter;
private int[] layouts;
private LinearLayout welcomeLayout;
private Button btnSkip, btnNext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Checking for first time launch - before calling setContentView()
prefManager = new PrefManager(this);
if (!prefManager.isFirstTimeLaunch()) {
launchHomeScreen();
finish();
}
setContentView(R.layout.activity_welcome);
viewPager = (ViewPager) findViewById(R.id.view_pager);
welcomeLayout = (LinearLayout) findViewById(R.id.welcomeLayout);
btnSkip = (Button) findViewById(R.id.btn_skip);
btnNext = (Button) findViewById(R.id.btn_next);
//add welcome slide layouts
layouts = new int[]{
R.layout.slide1,
R.layout.slide2,
R.layout.slide3};
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
btnSkip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchHomeScreen();
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// checking for last page
// if last page home screen will be launched
int current = getItem(+1);
if (current < layouts.length) {
// move to the next screen
viewPager.setCurrentItem(current);
} else {
launchHomeScreen();
}
}
});
}
private int getItem(int i) {
return viewPager.getCurrentItem() + i;
}
private void launchHomeScreen() {
prefManager.setFirstTimeLaunch(false);
startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
finish();
}
// viewpager change listener
ViewPager.OnPageChangeListener viewPagerPageChangeListener =
new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// changing the next button text 'NEXT' / 'GOT IT'
if (position == layouts.length - 1) {
// for the last page, make button text to GOT IT
btnNext.setText(getString(R.string.start));
btnSkip.setVisibility(View.GONE);
} else {
// still pages are left
btnNext.setText(getString(R.string.next));
btnSkip.setVisibility(View.VISIBLE);
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
};
/**
* View pager adapter
*/
public class MyViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;
public MyViewPagerAdapter() {
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(layouts[position], container, false);
container.addView(view);
return view;
}
@Override
public int getCount() {
return layouts.length;
}
@Override
public boolean isViewFromObject(View view, Object obj) {
return view == obj;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
}

Đừng quên đặt WelcomeActivity như trình khởi chạy trong tệp Manifest:

<activity android:name=".WelcomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Nút động

Các nút là một phần không tách rời của bất kỳ ứng dụng nào vì chúng liên lạc và cung cấp phản hồi khi nhấp vào. Trong thư mục drawable, thêm một tệp XML drawable (drawable/ripple.xml) sẽ sử dụng làm nền cho nút để đạt được hiệu ứng gợn sóng (ripple effect).

 <?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="#f816a463"
tools:targetApi="lollipop">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#f816a463" />
</shape>
</item>
</ripple>

Chỉnh sửa nút để sử dụng XML gợn sóng cho hình nền, như được hiển thị bên dưới.

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ripple"
android:padding="16dp"
android:text="Click Me" />

Bây giờ nút sẽ hiển thị gợn sóng khi chạm vào.

Bạn có thể thêm các hình động thú vị và hữu ích vào ứng dụng của mình bằng một số kỹ thuật đơn giản. Cần lưu ý rằng mặc dù hình ảnh động rất quan trọng để nâng cao trải nghiệm người dùng, nhưng lạm dụng hình động hoặc sử dụng chúng một cách không phù hợp cũng có thể làm giảm chất lượng trải nghiệm.

Chúc các bạn thực hiện thành công!