Thứ Tư, 6 tháng 3, 2019

Thuộc tính style trong các View lập trình Android

Chọn cách thiết lập thuộc mềm dẻo hơn cho các View

Những thuộc tính trên các View ảnh hướng đến sự hiện thị của nó như kích thước, màu sắc có thể gán trực tiếp giá trị mong muốn trong layout xml. Ví dụ TextView sau gán màu #DD2C00, khoảng padding là 10dp, khoảng margin là 8dp
 <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"

        android:textColor="#DD2C00"
        android:padding="10dp"
        android:layout_margin="8dp"  />
Code trình bày trên với cách nhập cố định các giá trịnh thuộc tính như vậy vẫn có được giao diện theo yêu cầu, nhưng có một bất lợi về tính mềm dẻo, khi bạn cần thay đổi giá trị bạn cần tìm tất cả các thuộc tính này và thay đổi từng cái một.
Giải pháp là các giá trị thuộc tính đó được gộp lại ở một file tài nguyên xml như colors.xml để định nghĩa các giá trị màu, dimens.xml để định nghĩa các kích thước ..., làm điều ngoài việc tập trung các giá trị thuộc tính lại một chỗ để dễ quản lý nó còn có lợi ích khi nhiều phần tử View sử dùng cùng giá trị thuộc tính nào đó thì ta chỉ việc thay đổi giá trị này khi cần thiết.
Ví dụ:
values/colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="mytextviewcolor">#DD2C00</color>
</resources>
values/dimens.xml
<resources>
    <dimen name="mytextviewpadding">10dp</dimen>
    <dimen name="mytextviewmargin">8dp</dimen>
</resources>
Lúc này quay trở lại layout, áp dụng các giá trị này sẽ là:
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"

    android:textColor="@color/mytextviewcolor"
    android:padding="@dimen/mytextviewpadding"
    android:layout_margin="@dimen/mytextviewmargin"  />

Thuộc tính style cho các View

Cách trên đã mang lại sự mềm dẻo đáng kể, tuy nhiên còn có cách thức mạnh mẽ hơn đó là gộp nhiều thuộc tính lại một chỗ trong file styles.xml, sau đó áp dụng vào View - Ví dụ định nghĩa một style có tên mytextviewstyle, trong nó có định nghĩa nhiều thuộc tính có thể gán vào View như: layout_with, textcolor ...
values/styles.xml
<resources>
    <style name="mytextviewstyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">@color/mytextviewcolor</item>
        <item name="android:layout_margin">@dimen/mytextviewmargin</item>
        <item name="android:padding">@dimen/mytextviewpadding</item>
    </style>
</resources>
Giờ muốn View nào áp dụng style này chỉ việc gán cho nó thông qua thuộc tính android:style, ví dụ trên trở thành:
<TextView 
    android:text="Hello World!" 
    style="@style/mytextviewstyle"/>
Sự linh hoạt và tập trung hoá cách sử dụng này được khuyến khích sử dụng, nhất là khi ứng dụng có độ phức tạp đáng kể nó sẽ trở lên rất quan trong vì tiết kiệm thời gian, dễ dàng giám sát, dễ dàng chỉnh sửa cập nhật. Hãy nhìn lại cách tạo ra TextView 3 trường hợp trên để nhận ra ưu điểm của nó:
<!--Nhập giá trí cố định, kém linh hoạt -->
 <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"

        android:textColor="#DD2C00"
        android:padding="10dp"
        android:layout_margin="8dp"  />
        
<!--Giá trị các thuộc tính được tập trung một nơi và sử dụng khi cần-->
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"

    android:textColor="@color/mytextviewcolor"
    android:padding="@dimen/mytextviewpadding"
    android:layout_margin="@dimen/mytextviewmargin"  />

<!--Các thuộc tính và giá trị của nó được gộp lại thành các style, cách ưu điểm nhất-->
<TextView 
    android:text="Hello World!" 
    style="@style/mytextviewstyle"/>
Thứ Năm, 14 tháng 2, 2019

Sử dụng Broadcast Intent BroadcastReceiver trong Android

Khái quát về Broadcast Intent

Các Broadcast Intent là các đối tượng (có chứa tên hành động - action - và dữ liệu) được lan truyền trong ứng dụng thông qua qua goi các phương thức của Activity là: sendBroadcast()sendOrderedBroadcast(). Khi đối tượng Broadcast Intent được tạo và gửi đi như vậy thì các ứng dụng trong hệ thống hoặc ở một phần khác của ứng dụng có thể nhận được đối tượng này nếu có đăng khi nhận bằng cách sử dụng Broadcast Receiver (Xem phần sau).
Ví dụ sau, tạo ra một Broadcast Intent sau đó gửi đi (lan truyền) trong ứng dụng:
String actionName = "my-first-broadcastintent";
Intent intent = new Intent(actionName);
//Thiết lập tên để cho Receiver nhận được thì biết đó là loại Intent
intent.setAction(actionName);
//Dữ liệu gắn vào Intent thiết lập bằng putExtra với (tên, dữ liệu), dữ liệu là
//các kiểu cơ bản Int, String ... hoặc các loại đối tượng lớp kế thừa từ Serializable
intent.putExtra("dataname", "Hello, How are you?");
//Thực hiện lan truyền Intent trong hệ thống
sendBroadcast(intent);

Gửi Broadcast Intent

Trong Activity có các phương thức để lan truyền đối tượng Broadcast Intent, tuỳ mục đích mà sử dụng một phương thức phù hợp
Phương thứcSử dụng
sendBroadcast(Intent intent)Gửi đi intent mà tất cả các BroadcastReceiver sẽ nhận được. Việc sử dụng phương thức này sẽ thực hiện luồng bất đồng bộ, nó sẽ trả về ngay lập tức và logic code sau lời gọi tiếp tục chạy còn phía nhận (BroadcastReceiver) chạy một quá trình khác khi nhận được intent - chúng nhận được theo một thứ tự không xác định thường là cùng lúc, tất nhiên bạn sẽ không nhận được kết quả trả về nào từ BroadcastReceiver và BroadcastReceiver cũng không thể ngăn chặn quá trình lan truyền.
sendOrderedBroadcastsendOrderedBroadcast (Intent intent, String receiverPermission) - việc lan truyền intent sẽ theo thứ tự, gửi đến từng BroadcastReceiver, thứ tự này có thể điều chỉnh qua thuộc tính android:priority tương tứng khi khai báo intent-filter, khi các BroadcastReceiver thi hành nó có thể truyền kết quả của của đến một BroadcastReceiver khác thậm chí ngắt luôn quá trình làn truyền intent để các BroadcastReceiver không nhận được intent.

Khái quát Broadcast Receiver

Các Broadcast Receiver là các đối tượng đăng ký với ứng dụng của bạn, nó có chức năng lắng nghe - chờ các Broadcast Intent gửi đến (Intent từ ứng dụng, từ ứng dụng khác, từ hệ thống Android), khi nhận được Intent nó thi hành các chức năng do bạn xây dựng.
Để xây dựng một Receiver tạo ra đối tượng từ lớp BroadcastReceiver hoặc từ các lớp tự xây dựng kế từ từ BroadcastReceiver, sau đó đăng ký nó với hệ thống bằng phương thức registerReceiver của Activity
Ví dụ sau tạo ra một lớp kế thừa từ BroadcastReceiver, bao giờ cũng phải triển khai phương thức onReceive của lớp này.
class MyBroadcastReceiver extends BroadcastReceiver {

    public static final String ACTION_FIRST_ACTION  = "my-first-broadcastintent";

    MyBroadcastReceiver() {
    }
    //Code thi hành khi Receiver nhận được Intent
    @Override
    public void onReceive(Context context, Intent intent) {

        //Kiểm tra Action của Intent nhận được có tên irst-broadcastintent
        if (intent.getAction().equals(MyBroadcastReceiver.ACTION_FIRST_ACTION)) {
            //Đọc dữ liệu trong Intent
            String d = intent.getStringExtra("dataname");
            Toast.makeText(context, d, Toast.LENGTH_SHORT).show();
        }
    }
}

Đăng ký BroadcastReceiver

Tạo ra đối tượng lớp MyBroadcastReceiver và đăng ký nó với hệ thống:
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();

IntentFilter intentFilter = new IntentFilter();

//Thiết lập các Action filter mà MyBroadcastReceiver sẽ nhận
intentFilter.addAction(MyBroadcastReceiver.ACTION_FIRST_ACTION);
registerReceiver(myBroadcastReceiver, intentFilter);

Huỷ Đăng ký BroadcastReceiver

Khi BroadcastReceiver không còn sử dụng nữa, cần thiết phải huỷ đăng ký nó khỏi hệ thống bằng phương thức unregisterReceiver, thường làm điều này trong onDestroy của Activity
@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(myBroadcastReceiver);
}
Ứng dụng ví dụ:
Intent Android
Xem đoạn code tại: MainActivity.java hoặc tải ví dụ mẫu tại: android-broadcastintent

Lắng nghe một số Intent của hệ thống Android

Có một số sự kiện hệ thống Android xảy ra như thay đổi kết nối mạng (mất mạng, có mạng), khởi động máy, tắt máy ..., nếu muốn bắt được các sự kiện đó hoàn toàn có thể dùng BroadcastReceiver như trên và đăng ký nhận Intent với Intent Filter có Action phù hợp, danh sách đầy đủ các Action xem tại: broadcast_actions và broadcast_actions
Một số Action quan trọng như:
  • android.intent.action.BATTERY_CHANGED (Intent.ACTION_BATTERY_CHANGED) thay đổi trạng thái PIN
  • android.intent.action.BATTERY_LOW (Intent.ACTION_BATTERY_LOW) PIN ở mức thấp
  • android.intent.action.BATTERY_OKAY (Intent.ACTION_BATTERY_OKAY) PIN vào trạng thái tốt (sạc lên mức cao)
  • android.intent.action.BOOT_COMPLETED (Intent.ACTION_BOOT_COMPLETED) Khởi động xong máy
  • android.intent.action.CALL_BUTTON (Intent.ACTION_CALL_BUTTON) bấm nút gọi
  • android.intent.action.DATE_CHANGED (Intent.ACTION_DATE_CHANGED) ngày thay đổi
  • android.intent.action.REBOOT (Intent.ACTION_REBOOT) khởi động máy
Ví dụ sau lắng nghe sự kiện khi PIN thay đổi (tăng, giảm):
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(myBroadcastReceiver, intentFilter);

Thứ Năm, 26 tháng 4, 2018

Sử dụng RelativeLayout trong Android

RelativeLayout là layout mà các View con được xác định vị trí bởi các mối liên hệ với View cha hoặc với View con như View con nằm dưới một View con khác, View con căn thẳng lề phải với View cha ...

RelativeLayout

RelativeLayout là layout mà nó hiện thị các view con nó chứa ở các vị trí trong mối liên hệ của chúng với nhau (như View con này nằm dưới một View con khác, View con này nằm bên trái một View con khác ...), kể cả mối liên hệ của chúng với chính phần tử cha RelativeLayout (như căn thẳng theo cạnh đấy của phần tử cha, nằm giữa phần tử cha, nằm bên trái phần tử cha ...).
RelativeLayout là một layout hết sức mạnh mẽ về độ tiện lợi và hiệu quả, nếu giao diện không ở mức quá phức tạp việc chọn RelativeLayout mạng lại hiệu suất còn tốt hơn ConstraintLayout. RelativeLayout dùng khi đơn giản, ConstraintLayout khi giao diện phức tạp.

Định vị và mối liên hệ các View con trong RelativeLayout

Định vị mặc định

Khi các View con đưa vào RelativeLayout nếu chưa có thiết lập mối liên hệ qua lại nào với phần tử cha hay với phần tử View con khác thì nó sẽ được định vị ở góc trên - trái của RelativeLayout. Như trường hợp dưới đây cả 3 View con không có thiết lập mối liên hệ nào, nên nó đều định vị ở góc trên / trái và vẽ chồng nên nhau, View con nào xếp sẽ ở lớp trên của màn hình.
<?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:layout_margin="8dp"
    android:background="#e2e3eb">

    <TextView
        android:id="@+id/view1"
        android:text="view1"
        android:gravity="center"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:background="#e8d33636" />

    <TextView
        android:id="@+id/view2"
        android:text="view2"
        android:gravity="center"
        android:layout_width="50dp"
        android:layout_height="200dp"
        android:background="#e71faf15" />
    <TextView
        android:id="@+id/view3"
        android:text="view3"
        android:gravity="center"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#d4a00f8f" />
</RelativeLayout>

android:gravity và android:ignoreGravity của RelativeLayout

Các View con khi đã định vị xong trong RelativeLayout, giả sử coi như tất cả các View con nằm vừa trong một đường biên chữ nhật, thì cả khối các View con này có thể dịch chuyển tới những vị trí nhất định trong RelativeLayout bằng thuộc tính: android:gravity, nó nhận các giá trị (có thể tổ hợp lại với ký hiệu | giống với LinearLayout)
Giá trịÝ nghĩa
centerCăn ở giữa
topỞ phần trên
bottomPhần dưới
center_horizontalỞ giữa theo chiều ngang
center_verticalỞ giữa theo chiều đứng
leftTheo cạnh trái
rightTheo cạnh phải
bottomCạnh dưới
Hình dưới là ví dụ, thiết lập android:gravity="center|right"
<?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:layout_margin="8dp"
    android:gravity="center|right"
    android:background="#e2e3eb">

    <!-- Các View con --!>

</RelativeLayout>
RelativeLayout có hỗ trợ chỉ ra một View con tách khỏi khối biên chữ nhật chứa các View con để phần tử đó không bị ảnh hưởng bởi gravity bằn thuộc tính android:ignoreGravity="id-view-con"
Ví dụ sau đã tách phần tử TextView có id: textview khỏi ảnh hưởng của gravity của RelativeLayout
<?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:layout_margin="8dp"

    android:gravity="center|right"
    android:ignoreGravity="@id/textview"


    android:background="#e2e3eb">
    <TextView
        android:id="@+id/textview"
        android:text="Example RelativeLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/view1"
        android:text="view1"
        android:gravity="center"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:background="#e8d33636" />

    <TextView
        android:id="@+id/view2"
        android:text="view2"
        android:gravity="center"
        android:layout_width="50dp"
        android:layout_height="200dp"
        android:background="#e71faf15" />
    <TextView
        android:id="@+id/view3"
        android:text="view3"
        android:gravity="center"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#d4a00f8f" />
</RelativeLayout>

Định vị View con bằng liên hệ với View cha RelativeLayout

Vị trí của View con trong RelativeLayout có thể thiết lập bằng cách chỉ ra mối liên hệ vị trí với view cha như căn thẳng cạnh trái View cha với View con, căn thẳng cạnh phải View cha với View con ... Các thuộc tính thực hiện chức năng này như sau
Thuộc tínhÝ nghĩa
android:layout_alignParentBottomtrue căn thẳng cạnh dưới view con với cạnh dưới View cha
android:layout_alignParentLefttrue căn thẳng cạnh trái view con với cạnh trái View cha
android:layout_alignParentRighttrue căn thẳng cạnh phải view con với cạnh phải View cha
android:layout_alignParentToptrue căn thẳng cạnh trên view con với cạnh trên View cha
android:layout_centerInParenttrue căn view con vào giữa View cha
android:layout_centerHorizontaltrue căn view con vào giữa View cha theo chiều ngang
android:layout_centerVerticaltrue căn view con vào giữa View cha theo chiều đứng
Ví dụ hình sau View có nền màu tím được định vị như vậy là do có hai thuộc tính android:layout_centerInParent="true" (làm cho View con nằm giữa) android:layout_alignParentRight="true" (làm cho View con căn thẳng cạnh phải với cạnh phải của View cha)
<TextView
        android:id="@+id/view3"

        android:layout_centerInParent="true"
        android:layout_alignParentRight="true"

        android:text="view3"
        android:gravity="center"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#d4a00f8f" />

Định vị View con bằng liên hệ giữa chúng với nhau

View con trong RelativeLayout ngoài mối liên hệ với View cha như trên, chúng có có thể thiết lập liên hệ với nhau ví dụ như View con này nằm phía trên một View con khác, nằm phía dưới một view con khác ...
Thuộc tínhÝ nghĩa
android:layout_belowNằm phía dưới View có ID được chỉ ra
android:layout_aboveNằm phía trên View có ID được chỉ ra
android:layout_toLeftOfNằm phía trái View có ID được chỉ ra
android:layout_toRightOfNằm phía phải View có ID được chỉ ra
android:layout_alignBottomCăn thẳng cạnh dưới với cạnh dưới của View có ID được chỉ ra
android:layout_alignLeftCăn thẳng cạnh trái với cạnh trái của View có ID được chỉ ra
android:layout_alignRightCăn thẳng cạnh phải với cạnh phải của View có ID được chỉ ra
android:layout_alignTopCăn thẳng cạnh trên với cạnh trên của View có ID được chỉ ra

Các android:layout_margin ... của View con

Về phía các cạnh của View con (left, top, right, bottom) nếu có mối liên hệ với View cha hoặc View con thì theo phía đó có thể thiết lập thêm thuộc tính về margin như: android:layout_marginLeft, android:layout_marginTop, android:layout_marginRight, android:layout_marginBottom để thiết lập khoảng cách của mối liên hệ đó.
Ví dụ sau sử dụng các liên hệ của View con và margin để định vị các View con
<?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:layout_margin="8dp"
    android:background="#e2e3eb">

    <TextView
        android:id="@+id/view1"
        android:text="view1"
        android:gravity="center"

    
        android:layout_toLeftOf="@id/view3"
        android:layout_alignBottom="@id/view3"

        android:layout_width="200dp"
        android:layout_height="50dp"
        android:background="#e8d33636" />

    <TextView
        android:id="@+id/view2"
        android:text="view2"
    

        android:layout_alignRight="@id/view1"
        android:layout_above="@id/view1"

        android:gravity="center"
        android:layout_width="50dp"
        android:layout_height="200dp"
        android:background="#e71faf15" />
    <TextView
        android:id="@+id/view3"
    

        android:layout_centerInParent="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="30dp"

        android:text="view3"
        android:gravity="center"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#d4a00f8f" />
</RelativeLayout>

Ví dụ màn hình đăng nhập RelativeLayout

<?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:layout_margin="8dp"
    android:gravity="center"
    android:background="#e2e3eb">


    <TextView
        android:id="@+id/textview"
        android:text="Đăng nhập"

        android:layout_centerHorizontal="true"
        android:textSize="20sp"
        android:textAllCaps="true"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/username"
        android:hint="Username"
        android:layout_below="@id/textview"
        android:layout_marginTop="40dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <EditText
        android:id="@+id/password"
        android:hint="passwords"
        android:inputType="textPassword"
        android:layout_below="@+id/username"
        android:layout_marginTop="8dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/btnLogin"

        android:layout_below="@id/password"
        android:layout_toLeftOf="@id/recoverypassword"

        android:text="Đăng nhập"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/recoverypassword"
        android:text="Quyên MK"

        android:layout_centerHorizontal="true"
        android:layout_below="@id/password"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/help"
        android:text="Trợ giúp"

        android:layout_below="@id/password"
        android:layout_toRightOf="@id/recoverypassword"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>

Danh mục Gửi liên hệ

Loading...