Day 18 - ShowcaseView

สวัสดีครับ บทความนี้เป็นบทความที่ 18 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days
สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ
- Day 1 : AndroidStaggered Grid
- Day 2 : Paralloid
- Day 3 : Retrofit
- Day 4 : SwipeRefreshLayout
- Day 5 : Android GraphView
- Day 6 : Holo Color Picker
- Day 7 : Android Async Http
- Day 8 : Crashlytics
- Day 9 : Butter Knife
- Day 10 : Android Annotations
- Day 11 : DateTimePicker
- Day 12 : Circular Progress Button
- Day 13 : ViewPager
- Day 14 : ViewPagerIndicator
- Day 15 : FadingActionBar
- Day 16 : AutofitTextView
- Day 17 : SwipeListView
- Day 18 : ShowcaseView
- Day 19 : GreenDAO
- Day 20 : AndroidViewAnimation
- Day 21 : ActiveAndroid
- Day 22 : Twitter4J
- Day 23 : ListViewAnimations
- Day 24 : AndEngine
- Day 25 : EazeGraph
- Day 26 : Cardslib
- Day 27 : AdapterKit
- Day 28 : WeatherLib
- Day 29 : FlatUI
- Day 30 : Android Firebase
สำหรับวันนี้ขอนำเสนอเรื่อง ShowcaseView เป็น Library ที่เอาไว้ทำเป็น Guide หรือ Showcase ให้แอพของเรา โดยโฟกัสไปยังตำแหน่งที่เราต้องการครับ
Installation
ขั้นตอนการติดตั้ง เพิ่ม dependencies ลงไปที่ไฟล์ build.gradle
(ไฟล์ภายใน Module)
dependencies { compile ('com.fortysevendeg.swipelistview:swipelistview:1.0-SNAPSHOT@aar') { transitive = true }}
ต่อจากนั้นก็เพิ่ม Maven Central ที่ไฟล์ build.gradle
ใน Root Project ดังนี้
repositories { mavenCentral()}
ต่อมาทำการดาวน์โหลดตัว Library มาไว้ในโปรเจ็คของเรา จากนั้นก็ เปิดไฟล์ settings.gradle
แล้วทำการ include Library ที่โหลดมาเมื่อกี้ให้ถูกต้อง
include ':libs:showcaseview:library'
ด้านบน ผมเซฟตัว Library ไว้ในโฟลเดอร์ libs
ชื่อโปรเจ็คว่า showcaseview และตัวโมดูลชื่อว่า library
ทำกด Sync Project with Gradle File เป็นอันเรียบร้อย
Getting Started
การใช้งาน ShowcaseView
จะมีโค๊ดดังนี้
new ShowcaseView.Builder(this) .setTarget(new ActionViewTarget(this, ActionViewTarget.Type.HOME)) .setContentTitle("ShowcaseView") .setContentText("This is highlighting the Home button") .setOnClickListener(this) .build();
ลักษณะการสร้าง ShowcaseView จะคล้ายๆกับการทำ AlertDialog เพราะใช้ Builder Pattern เหมือนกัน เรามาดูว่าจากโค๊ดด้านบน คืออะไรบ้าง
setTarget()
: ตัวนี้เป็นการระบุว่า จะให้มันโฟกัสไปยังตำแหน่งที่เราต้องการsetContentTitle()
: ใส่ Title ให้กับ ShowcaseViewsetContentText()
: ใส่ข้อความรายละเอียดให้กับ showcaseViewsetOnClickListener()
: เอาไว้รับ Listener เมื่อมีการกดปุ่ม Button
Create Project
มาลองสร้างโปรเจ็คกันเลยดีกว่าครับ จะได้เห็นภาพว่ามันใช้งานยังไง? เริ่่มแรกทำการสร้างไฟล์เลเอาท์ขึ้นมา 1 ไฟล์ ชื่อว่า activity_showcaseview.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:scaleType="centerCrop" android:src="@drawable/guitar" />
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#8831415a" android:id="@+id/relative_layout" android:padding="16dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp" android:textColor="@color/white" android:text="@string/step1" android:id="@+id/step1" android:layout_marginTop="32dp" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp" android:textColor="@color/white" android:text="@string/step2" android:id="@+id/step2" android:layout_alignParentBottom="false" android:layout_alignParentRight="false" android:layout_centerInParent="true" />
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:textColor="@color/white" android:text="@string/step3" android:id="@+id/step3" android:layout_alignLeft="@+id/step1" android:layout_marginBottom="36dp" android:singleLine="false" android:layout_alignParentBottom="true" /> </RelativeLayout>
</RelativeLayout>
ไฟล์ res/values/strings.xml
ที่ใช้กับเลเอาท์ด้านบน
<resources> <string name="step1">Step 1 : Learn Android</string> <string name="step2">Step 2 : Make First App</string> <string name="step3">Step 3 : Practice, Practice and Practice</string> <string name="help">Help</string></resources>
ส่วนรูปภาพ ใครอยากเปลี่ยนรูปหรือลบทิ้งก็ได้ครับ แต่ถ้าจะเอารูปภาพตามตัวอย่าง ก็โหลดจากนี้ guitar
เมื่อออกแบบเลเอาท์เสร็จแล้ว จะได้ลักษณะแบบนี้
ต่อมาสร้างไฟล์ ShowcaseViewActivity.java
ขึ้นมา จากนั้นก็ทำการเชื่อม View จาก Layout แบบปกติครับ ดังนี้
public class ShowcaseViewActivity extends ActionBarActivity {
private TextView mStep1, mStep2, mStep3; private ShowcaseView mShowcaseView; private int mState = 0;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.day18_activity_showcaseview);
mStep1 = (TextView) findViewById(R.id.step1); mStep2 = (TextView) findViewById(R.id.step2); mStep3 = (TextView) findViewById(R.id.step3); }}
ต่อมาทำการสร้างออปเจ็ค ShowcaseView ขึ้นมาแบบนี้
mShowcaseView = new ShowcaseView.Builder(this) .setTarget(new ViewTarget(mStep1)) .build();mShowcaseView.setButtonText("Next Step");
จะเห็นว่าด้านบน ผมทำการเซตค่า Button ให้ชื่อว่า Next Step และทำการ setTarget()
ไปที่ step1 นั่นก็คือ TextView ตัวบนสุดครับ
ส่วนวิธีการสร้าง Target
ทำได้ 2 แบบครับ คือ
new ViewTarget(view);
: โดย view ต้องเป็น view ที่เราทำการfindViewById()
แล้วnew ViewTarget(id, Activity)
: parameter ตัวแรก คือ id ของ View เช่นR.id.step1
และตัวสองคือActivity
ลองทดสอบรันดูครับ ผลลัพธ์จะได้ดังภาพ
จะเห็นว่ามันมีวงกลมไปโฟกัส ที่ตำแหน่ง TextView ที่ชื่อ mStep1
ที่เรา setTarget
ไว้ และก็มี Button ปุ่มขวาล่างที่เราตั้งชื่อว่า Next Step
ทีนี้ลองเปลี่ยนจาก mStep1
เป็น mStep2
ดูครับ
.setTarget(new ViewTarget(mStep2))
ลองรันใหม่อีกครั้ง
แต่ว่าเมื่อเรากดปุ่ม Button ตัว ShowcaseView มันก็จะหายไปทันที ทีนี้เราจะทำยังไง เมื่อกด ก็ให้มันไล่ไปทีละสเตปๆ เริ่มจาก mStep1
ไปจนถึง mStep3
ครับ
ตัว ShowcaseView มี Listener ให้เหมือนกันครับ เอาไว้รับ listener เหมือน Button ปกติเลยครับ กลับไปแก้ไขตรง ShowcaseView.Builder()
ให้ครับ โดยเพิ่ม setOnClickListener(ShowcaseViewOnClick)
ไปก่อนที่จะทำการ build()
เป็นดังนี้
mShowcaseView = new ShowcaseView.Builder(this) .setTarget(new ViewTarget(mStep1)) .setOnClickListener(ShowcaseViewOnClick) .build();mShowcaseView.setButtonText("Next Step");
ทีนี้ก็สร้าง interface ShowcaseViewOnClick
ขึ้นมา (จริงๆ ใครถนัดทำ anonymous inner class ก็ได้นะครับ หรือจะ implements interface แล้ว override เมธอด onClick
เอาก็ได้เหมือนกัน แต่ผมชอบวิธีนี้มากกว่า)
เรื่องที่เกี่ยวข้อง : Android Button และการรับ Event ด้วย OnClick
View.OnClickListener ShowcaseViewOnClick = new View.OnClickListener() { @Override public void onClick(View v) { switch (mState) { case 0: mShowcaseView.setShowcase(new ViewTarget(mStep2), true); // mShowcaseView.setTarget(new ViewTarget(mStep2)); break; case 1: mShowcaseView.setShowcase(new ViewTarget(mStep3), true); // mShowcaseView.setTarget(new ViewTarget(mStep3)); break; case 2: ActionViewTarget target = new ActionViewTarget(ShowcaseViewActivity.this, ActionViewTarget.Type.OVERFLOW); mShowcaseView.setTarget(target); break; default: mShowcaseView.hide(); mLayout.setBackgroundColor(Color.TRANSPARENT); setVisible(true); break; } mState += 1; }};
ข้อควรระวัง import OnClickListener
ให้ถูก package ด้วยนะครับ ต้องเป็น
import android.view.View.OnClickListener;
จะเห็นว่าใน onClick()
ผมทำการเพิ่มค่า mState
ทุกครั้งที่มีการคลิก Button จากนั้นก็ทำ switch case เช็คว่า ถ้ากดครั้งแรก ให้ไปที่ step2 กดครั้งที่สองให้ไป Step3 กดครั้งที่สามไปบน ActionBar และกดครั้งสุดท้าย จะเป็นการซ่อน ShowcaseView
setShowcase(Target, animation);
: จะโฟกัสและทำการเล่น Animation ด้วย หากค่าเป็น truesetTarget(Target);
: จะแค่โฟกัสอย่างเดียว ไม่มีการเล่น animation
สุดท้ายผมทำการแก้โค๊ดใหม่ แล้วลองทดสอบอีกครั้งครับ โดยเพิ่มในส่วน menu เข้าไปด้วย res/menu/menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_item" android:title="@string/help" app:showAsAction="never"/></menu>
สุดท้ายเพิ่ม onCreateOptionsMenu
ลงไป และโค๊ดทั้งหมดเป็นแบบนี้
package com.devahoy.learn30androidlibraries.day18;
import android.graphics.Color;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.RelativeLayout;import android.widget.TextView;
import com.devahoy.learn30androidlibraries.R;import com.github.amlcurran.showcaseview.ShowcaseView;import com.github.amlcurran.showcaseview.targets.ActionViewTarget;import com.github.amlcurran.showcaseview.targets.Target;import com.github.amlcurran.showcaseview.targets.ViewTarget;
public class ShowcaseViewActivity extends ActionBarActivity {
private TextView mStep1, mStep2, mStep3; private ShowcaseView mShowcaseView; private RelativeLayout mLayout; private int mState = 0;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.day18_activity_showcaseview);
mStep1 = (TextView) findViewById(R.id.step1); mStep2 = (TextView) findViewById(R.id.step2); mStep3 = (TextView) findViewById(R.id.step3); mLayout = (RelativeLayout) findViewById(R.id.relative_layout); }
View.OnClickListener ShowcaseViewOnClick = new View.OnClickListener() { @Override public void onClick(View v) { switch (mState) { case 0: mShowcaseView.setShowcase(new ViewTarget(mStep2), true);// mShowcaseView.setTarget(new ViewTarget(mStep2));
break; case 1: mShowcaseView.setShowcase(new ViewTarget(mStep3), true);// mShowcaseView.setTarget(new ViewTarget(mStep3)); break; case 2: ActionViewTarget target = new ActionViewTarget(ShowcaseViewActivity.this, ActionViewTarget.Type.OVERFLOW);// mShowcaseView.setTarget(target); mShowcaseView.setTarget(target); mLayout.setBackgroundColor(Color.parseColor("#FF31415A")); mShowcaseView.setContentTitle("This is Help Menu"); setVisible(false); mShowcaseView.setButtonText("OK"); break; default: mShowcaseView.hide(); mLayout.setBackgroundColor(Color.TRANSPARENT); setVisible(true); break; } mState += 1; } };
public void setVisible(boolean isVisible) { if(isVisible) { mStep1.setVisibility(View.VISIBLE); mStep2.setVisibility(View.VISIBLE); mStep3.setVisibility(View.VISIBLE); } else { mStep1.setVisibility(View.GONE); mStep2.setVisibility(View.GONE); mStep3.setVisibility(View.GONE); } }
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu);
mShowcaseView = new ShowcaseView.Builder(this) .setTarget(new ViewTarget(mStep1)) .setOnClickListener(ShowcaseViewOnClick) .build();
mShowcaseView.setButtonText("Next Step");
return super.onCreateOptionsMenu(menu); }
@Override public boolean onOptionsItemSelected(MenuItem item) { return true; }}
ได้ผลลัพธ์เป็นที่น่าพอใจครับ กด Button ก็จะเลื่อนสเตปไปเรื่อยๆ
สรุป
ตัว ShowcaseView ผมว่าเหมาะเอาไปทำพวก Tutorial หรือแนะนำการใช้แอพสำหรับผู้ใช้งานใหม่ หรือแนะนำเมนูว่ามีเมนูอะไรบ้าง ตำแหน่งนี้ทำอะไร น่าจะเหมาะอยู่ครับ และการใช้งานก็ไม่ยุ่งยากด้วย ลองนำไปประยุกต์และใช้กันดูนะครับ Happy Coding :D
Source Code
References
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust