หากใครได้อ่านตรง Profile ก็จะเห็นได้ว่านอกจากนักอ่านแล้วผมยังเป็นนักเขียนโปรแกรม ( Programmer ) อีกด้วย ที่จริงผมอยากจะทำบทความเกี่ยวกับสอนเขียนโปรแกรม Android มานานแล้ว แต่ติดที่ว่าขี้เกียจและความรู้ไม่คั่อยแน่น เลยพลัดมาเรื่อยๆ จนวันนี้เกิดอยากแบ่งปันขึ้นมาเลยมาเขียน
ผมก็หัดเขียน Android ได้ไม่นาน รู้แค่พื้นฐาน ก็ถือซะว่าเรามาเรียนรู้ไปด้วยกันเลยแล้วกันนะครับ
วันนี้เริ่มกันด้วย TextView แบบวิ่งกันดีกว่า ลองนึกถาพตัวอักษรวิ่งๆที่อยู่ด้านล่างของพวกรายการข่าวในทีวีก็คงจะนึกออก ซึ่งก็มีคนทำเอาไว้แล้ว ชื่อว่า MarqueeView โดยวิธีใช้ก็ไม่ได้อยากอะไร เดี๋ยวเรามาลองทำกันดู
Source https://github.com/ened/Android-MarqueeView
เริ่มแรกก็สร้าง Project ขึ้นมาก่อน ของผมเลือกเป็น Blank Activity with Fragment
จากนั้นเข้าไปที่ build.gradle ของ Project ตามรูปด้วยล่าง ดูว่าเราใช้ respositories ของ mavenCentral() หรือไม่ ถ้ายังไม่มีก็เติมซะนะ
จากนั้นก็เข้าไปที่ build.gradle(Module:app) เพิ่ม Code ด้านล่างใน dependencies
build.gradle(Module:app)
[xml]dependencies {
…
compile ‘asia.ivity.android:marqueeview:1.1.5’
}[/xml]
ลองกด Syn Now ดู ถ้าผ่านก็ OK ไปกันต่อได้
ต่อไปเราจะมาทำส่วนของ Layout กัน โดย Layout หลักของผมคือ activity_main.xml แต่ข้างในเป็น Fragment เลยทำให้ Layout จริงของผมคือ fragment_main.xml
[xml title=”fragment_main.xml”] <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:marquee="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:text="First MarqueeView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
/>
<asia.ivity.android.marqueeview.MarqueeView
android:id="@+id/marqueeView"
android:layout_width="100dp"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do."
android:singleLine="true"
android:ellipsize="end"
tools:ignore="HardcodedText"/>
</asia.ivity.android.marqueeview.MarqueeView>
</LinearLayout>
</RelativeLayout>
[/xml]อย่าลืมใส่บรรทัดที่ 3 xmlns:marquee=http://schemas.android.com/apk/res-auto ตามรูปนะครับเดี๋ยวจะ Error
มาอธิบายให้เข้าใจกันอีกนิดดีกว่า จะเห็นว่าจะมี android:id=”@+id/marqueeView” ซึ่งเอาไว้กำหนดขนาดของกรอบที่ตัวอักษรจะแสดง เช่นตัวอย่างกำหนดความกว้างเป็น layout_width=”100dp” คือจะแสดงตัวอักษรแค่ความกว้าง 100dp เท่านั้น(กำหนดเป็น match_parent ก็ได้นะ) ถ้าประโยคของเราเกินจากนี้จะไม่แสดงต้องรอมันเลื่อนเอง
ส่วน textview android:id=”@+id/textView1” เอาไว้กำหนดตัวอักษรที่จะแสดง ตามปกติทั่วไป
จากนั้นเรามาทำส่วนของ Code กันบ้างไปกันที่ MainActivity.java ของผมเป็น Fragment เลยขอข้ามไปดูที่ตรงกำหนดค่าใน Fragment เลยแล้วกันนะครับ ใน onCreateView ให้เพิ่ม Code ด้านล่างนี้ลงไป
[java title=”MainActivity.java”] import android.support.v7.app.ActionBarActivity;import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import asia.ivity.android.marqueeview.MarqueeView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@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);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
final MarqueeView mv = (MarqueeView) rootView.findViewById(R.id.marqueeView);
mv.setPauseBetweenAnimations(500); //Set stop time when finish
mv.setSpeed(10); //Set speed
getActivity().getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mv.startMarquee();
}
});
return rootView;
}
}
}
การเรียก MarqueeView ก็เหมือนกับการประกาศ Textview ธรรมดา แค่เปลี่ยนเป็น MarqueeView
ส่วนการกำหนดเวลาตอนที่ตัวอักษรวิ่งจนหมดคำแล้วหยุดให้กำหนดโดยคำสั่ง
[java]mv.setPauseBetweenAnimations(500);[/java]
ส่วนการกำหนดความเร็วในการเลื่อนตัวอักษาให้กำหนดโดยคำสั่ง
[java]mv.setSpeed(10);[/java]
จากนั้นเรียก Runnable เพื่อสั่งให้ตัวอักษรเริ่มทำการเลื่อนด้วย
[java]
getActivity().getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mv.startMarquee();
}
});
[/java]
จากนั้นลองกด Run ดู ผลออกมาตัวอักษรของเราจะทำการเลื่อนแล้ว
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:marquee="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:text="First MarqueeView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
/>
<asia.ivity.android.marqueeview.MarqueeView
android:id="@+id/marqueeView"
android:layout_width="100dp"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do."
android:singleLine="true"
android:ellipsize="end"
tools:ignore="HardcodedText"/>
</asia.ivity.android.marqueeview.MarqueeView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/btnStop"
android:text="Stop"
android:layout_width="0dp"
android:layout_weight="50"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btnStart"
android:text="Start"
android:layout_width="0dp"
android:layout_weight="50"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
[/xml]
เราเพิ่ม Button 2 อัน กำหนด id ว่า btnStart และ btnStop
จากนั้นมาที่ MainActivity.java เพื่อกำหนดให้กับการกดปุ่ม ที่ btnStart เราจะกำหนดให้เมื่อกดปุ่ม ตัวอักษรจะเริ่มเลื่อน และ btnStop เราจะกำหนดให้เมื่อกดปุ่ม ตัวอักษรจะหยุดเลื่อน โดยเพิ่ม Code ด้านล่างเพิ่มจากของเดิม
[java title=”MainActivity.java”] @Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
final MarqueeView mv = (MarqueeView) rootView.findViewById(R.id.marqueeView);
mv.setPauseBetweenAnimations(500); //Set stop time when finish
mv.setSpeed(10); //Set speed
getActivity().getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mv.startMarquee();
}
});
rootView.findViewById(R.id.btnStart).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mv.startMarquee();
}
});
rootView.findViewById(R.id.btnStop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mv.reset();
}
});
return rootView;
}
[/java]
ลอง Run ดูครับ เมื่อเรากด Start ตัวTextจะเริ่มเลื่อนใหม่ตั้งแต่แรก เมื่อกด Stop ตัวTextจะหยุดเลื่อน
เป็นอย่างไรกันบ้างครับกับ Library ตัวอักษรเลื่อนนี้ คงไม่ยากใช่มั้ยครับ วันหลังผมจะหา Library ตัวอื่นๆมาฝากอีกนะครับ โชคดี
Source Codeโหลดได้จาก Github หรือ Zip
[java title=”MainActivity.java”] package com.kamonway.blog_movingtext;import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import asia.ivity.android.marqueeview.MarqueeView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@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);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
final MarqueeView mv = (MarqueeView) rootView.findViewById(R.id.marqueeView);
mv.setPauseBetweenAnimations(500); //Set stop time when finish
mv.setSpeed(10); //Set speed
getActivity().getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
mv.startMarquee();
}
});
rootView.findViewById(R.id.btnStart).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mv.startMarquee();
}
});
rootView.findViewById(R.id.btnStop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mv.reset();
}
});
return rootView;
}
}
}
[/java]
[xml title=”fragment_main.xml”]
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:marquee="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:text="First MarqueeView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
/>
<asia.ivity.android.marqueeview.MarqueeView
android:id="@+id/marqueeView"
android:layout_width="100dp"
android:layout_height="wrap_content"
>
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do."
android:singleLine="true"
android:ellipsize="end"
tools:ignore="HardcodedText"/>
</asia.ivity.android.marqueeview.MarqueeView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/btnStop"
android:text="Stop"
android:layout_width="0dp"
android:layout_weight="50"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btnStart"
android:text="Start"
android:layout_width="0dp"
android:layout_weight="50"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
[/xml]