Bài 11. GridView và Spinner


1. GridView

Khi bạn muốn hiện thị các dữ liệu của mình theo 1 dạng lưới nào đó thì Android cung cấp cho bạn 1 control đó là GridView. GridView trong Android hoàn toàn tương tự như ListView, dữ liệu được đưa vào GridView thông qua các mảng 1 chiều và dựa vào số cột của GridView để ngắt số hàng và cột nhưng dựa vào số cột ta thiết lập mà nó tự động ngắt hàng

- Vậy có thể hiển thị Text hoặc hình ảnh vào GridView. Có thể thiết lập số cột cho GridView theo hình dưới đây:

gridview1

- Ta chỉ thiết lập Android:numColumns="3". Tức là Gridview sẽ ngắt dòng khi đủ 3 phần tử, nó chỉ khác chỗ này, còn việc đưa dữ liệu lên như thế nào thì nó giống như làm với ListView.

Ví dụ 1: Hiển thị văn bản lên GridView

- Bạn tạo một Android Project tên tùy thích, ở đây mình đặt tên: Vidu_Gridview_Text

- Đây là activity_main.xml cho ứng dụng:

<LinearLayout
    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:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
        android:orientation="vertical"
        tools:context=".MainActivity"
        android:weightSum="1">
        <TextView
            android:id="@+id/selection"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffde0c0f"
            android:hint="apps1pro"
        />
        <GridView
            android:layout_width="match_parent"
            android:layout_height="303dp"
            android:id="@+id/gridView"
            android:layout_weight="1.08"
            android:numColumns="3"/>
    </LinearLayout>

- Dòng 21 là id của GridView, ta để mặc định GridView.

- Dòng 23 có thuộc tính: Android:numColumns= "3", tức là dữ liệu sẽ được hiển thị trong Gridview với định dạng 3 cột.

 

Tiếp theo bạn xem MainActivity.java:

public class MainActivity extends ActionBarActivity{// đoạn xóa title
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        // xóa thanh notificotion 
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
        //Dùng mảng 1 chiều hoặc ArrayList để lưu một số dữ liệu
	String arr[]={"ASUS","DELL","SamSung","HP","APPLE","HTC","Blackberry","G Phone","FPT - Phone","HK Phone"};
	protected void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	//Tối tượng này dùng để hiển thị phần tử được chọn trong GridView
	final TextView selection=(TextView)
	findViewById(R.id.selection);
	final GridView gv=(GridView) 
        findViewById(R.id.gridView1);
	//Gán DataSource vào ArrayAdapter
	Array Adapter da=newArrayAdapter(this,Android.R.layout.simple_list_item_1,arr);
	//gán Datasource vào GridView
	gv.setAdapter(da);
	//Thiết lập sự kiện cho GridView,
	gv.setOnItemClickListener(newAdapterView.OnItemClickListener(){
	publicvoid onItemClick(AdapterView<?> arg0,View arg1,int arg2,long arg3)
	 {
	//Hiển thị phần tử được chọn trong GridView lên TextView
	selection.setText(arr[arg2]);
	}
	});
	}
	}

- Bạn thấy đó, cách sử dụng GridView là giống như ListView, nên nếu như bạn đã rành về ListView rồi thì GridView hiển nhiên bạn cũng làm tốt.

Thực thi chương trình bạn sẽ thấy như hình bên dưới: 

gd2

 

Ví dụ 2 sẽ phức tạp hơn, hiển thị danh sách hình ảnh có sẵn lên GridView, mỗi lần chọn vào hình ảnh nào thì sẽ hiển thị chi tiết ảnh đó trên một màn hình mới:

- Có thể Demo này đã có nhiều website và ebooks làm rồi, ở đây mình cũng muốn demo lại cho các bạn.

  • Bạn xem giao diện của ứng dụng trước:

dm

- Bên trái là màn hình chính cho phép hiển thị danh sách hình ảnh vào GridView, mỗi lần chọn vào từng hình trong GridView thì sẽ mở hình được chọn đó vào một màn hình mới (ví dụ như khi chọn hình chú Cừu thì nó sẽ hiển thị ra như màn hình bên phải ), nhấn nút Back để trở về màn hình chính.

- Ở đây có một sự khác biệt lớn đó là chúng ta chỉ sử dụng 1 MainActivity, không hề tạo thêm bất kỳ một Activity nào khác, chúng ta chỉ thay đổi Layout mà thôi. Nên nó cũng là điểm nhấn của ứng dụng.

-Hãy tạo một Android Project tên: demo_gridview và xem cấu trúc của chương trình khi dùng Eclipse và Android Studio:

gr5

- Có 2 Layout:

  • activity_main.xml là của màn hình chính dùng để hiển thị danh sách hình ảnh.
  • hinh.xml là dùng để hiển thị từng hình riêng lẻ.

- Tạo thêm thư mục drawble và kéo thả một số hình ảnh vào.

-  Phần class có 2 class: MainActivity và MyImageAdapter kế thừa từ BaseAdapter.

- Bây giờ ta đi vào chi tiết của từng cái:

- activity_main.xml:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <TextView
        android:id="@+id/tvMsg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="3dp"
        />
    <GridView
        android:id="@+id/gridView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:numColumns="3"
        >
    </GridView>
</LinearLayout>

- Bạn có thể nhìn vào hình trên để làm.

- Thứ nhất là class MyImageAdapter:

+ class này sẽ kế thừa từ BaseAdapter, và dùng để hiển thị từng hình ảnh riêng lẻ:

public class MyImageAdapter extends BaseAdapter{
	 private Context mContext;
	 private Integer[] mThumbIds;
	 public MyImageAdapter(Context c)
	{
	 		mContext=c;
	 }
	 public MyImageAdapter(Context c,Integer[]arrIds)
	{
	 mContext=c;
	 		mThumbIds=arrIds;
	 }
	 public int getCount()
	 	{
	 return mThumbIds.length;
	}
	 public Object getItem(int arg0)
	 {
	 returnnull;
	 	}
	 public long getItemId(int arg0)
	 	{
	 return0;
	 	}
	 /**
	 * Cần override lại hàm này để hiển thị hình ảnh
	 
	 */
	 
	 @Override
	 public View getView(int arg0,View convertView,ViewGroup arg2) 
	{
	 ImageView imgView;
	 if(convertView==null){
	 		imgView=newImageView(mContext);
	 		//can chỉnh lại hình cho đẹp
	 imgView.setLayoutParams(newGridView.LayoutParams(85,85));
	 imgView.setScaleType(ImageView.ScaleType.CENTER_CROP);
	 imgView.setPadding(8,8,8,8);
	 }
	else  {
	 imgView=(ImageView) convertView;
	 }
	 //lấy đúng vị trí hình ảnh được chọn
	 //gán lại ImageResource
	 		imgView.setImageResource(mThumbIds[arg0]);
	 return imgView;
	 }
	
	}

- Thứ hai là class MainActivity:

public class MainActivity extends Activityimplements OnItemClickListener{TextView tvMsg;
	GridView gv;
	TextView tvSoloMsg;//mảng lưu danh sách các id hình ảnh có sẵnInteger[]mThumbIds;//Adapter cho GridView
MyImageAdapter adapter=null;//Vì không tạo thêm 1 Activity nên lấy luôn 2 Id ở bên solo_picture.xmlImageView ivSoloPicture;Button btnBack;//Lưu Bundle backup cho MainActivity Bundle myBackupBundle;
protected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);//Lưu savedInstanceState trước vào myBackupBundle myBackupBundle=savedInstanceState; setContentView(R.layout.activity_main); setTitle("demo_gridview"); tvMsg=(TextView) findViewById(R.id.tvMsg);//gán mảng các Id hình ảnh cho mThumbIds mThumbIds=newInteger[]{R.drawable.a1,R.drawable.a2, R.drawable.a3,R.drawable.a4 }; gv=(GridView) findViewById(R.id.gridView1);//thiết lập Datasource cho Adapter adapter=newMyImageAdapter(this, mThumbIds);//gán Adapter vào Gridview gv.setAdapter(adapter);//thiết lập sự kiện để mở từng hình ảnh chitiết gv.setOnItemClickListener(this);}publicvoid onItemClick(AdapterView<?> arg0,View arg1,int arg2,long arg3){//gọi hàm xem hình ảnh chi tiết tại ví trí thứ arg2 showdetail(arg2);}publicvoid showdetail(int posistion){//Không mở Activity mới mà chỉ thiết lập lại Layout setContentView(R.layout.hinh); setTitle("demo_gridview");//Vừa gọi hàm trên thì màn hình sẽ thay đổi qua cái mới//ta lấy các control trong layout mới này tvSoloMsg=(TextView) findViewById(R.id.tvSoloMsg); tvSoloMsg.setText("Image at "+(posistion+1)); ivSoloPicture=(ImageView) findViewById(R.id.imgSolo);//thiết lập hình ảnh đang chọn lên ImageView mới ivSoloPicture.setImageResource(mThumbIds[posistion]); btnBack=(Button) findViewById(R.id.btnBack);//Thiết lập sự kiện click Back để phục hồi lại MainActivity//bằng cách gọi lại onCreate(myBackupBundle); btnBack.setOnClickListener(newView.OnClickListener(){ publicvoid onClick(View arg0){ onCreate(myBackupBundle);}});}}

- Khởi chạy ứng dụng bạn sẽ có kết quả như mong muốn.

Bài tập này bạn đã biết cách sử dụng GridView, biết cách đưa hình ảnh vào GridView, đặc biệt biết thêm một kỹ thuật mới đó là thay đổi Layout để đổi màn hình không cần chạy Activity.


2. Spinner

 Tương tự như  ComboBox trong C#, tương tự  như JComboBox trong Java.

- Nếu bạn đã hiểu về ListView thì việc hiểu Spinner là chuyện thường.

- Cách đổ dữ liệu lên Spinner là y xì như đổ lên ListView, nó chỉ khác một chỗ duy nhất trong ArrayAdapter đó là ta phải gọi setDropDownViewResource.

- Bạn xem hình ví dụ dưới đây về Spinner:

gr12

 - Ví dụ trên làm rất đơn giản, bạn chỉ việc kéo 2 control TextView và Spinner vào ứng dụng (xemactivity_spinner.xml):

<LinearLayoutxmlns:Android="http://schemas.Android.com/apk/res/Android"
 xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/LinearLayout1"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical"
    tools:context=".SpinnerActivity">
 <TextView
    Android:id="@+id/selection"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:background="#007380"
    Android:hint="selected here"
    Android:textColor="#ff003c"/>
 <Spinner
    Android:id="@+id/spinner1"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"/>
</LinearLayout>

- Ở đây ta đặt Id cho spinner là spinner1 (nhìn dòng lệnh 16).

  • Code SpinnerActivity.java:
public class MainActivity extends Activity{
//Tạo một mảng dữ liệu giả
	 String arr[]={"Hàng điện tử","Hàng hóa chất","Hàng gia dụng"};
	 TextView selection;
	 @Override
	 protected void onCreate(Bundle savedInstanceState) 
	{
	 super.onCreate(savedInstanceState);
	 	setContentView(R.layout.activity_main);
	 selection =(TextView) findViewById(R.id.selection);
	 //Lấy đối tượng Spinner ra
	 	Spinner spin=(Spinner) findViewById(R.id.spinner1);
	 //Gán Data source (arr) vào Adapter
	 ArrayAdapter adapter=newArrayAdapter
	 (this,Android.R.layout.simple_spinner_item, arr );
	 //phải gọi lệnh này để hiển thị danh sách cho Spinner
	adapter.setDropDownViewResource (Android.R.layout.simple_list_item_single_choice);
	 //Thiết lập adapter cho Spinner
	 spin.setAdapter(adapter);
	 //thiết lập sự kiện chọn phần tử cho Spinner
	 spin.setOnItemSelectedListener(newMyProcessEvent());
	 }
	 //Class tạo sự kiện
	 private class MyProcessEvent implements OnItemSelectedListener
	 {
	 //Khi có chọn lựa thì vào hàm này
	 public void onItemSelected(AdapterView<?> arg0,View arg1,int arg2,long arg3) 
	{
	 	//arg2 là phần tử được chọn trong data source
	 selection.setText(arr[arg2]);
	 }
	 //Nếu không chọn gì cả
	 public void onNothingSelected(AdapterView<?> arg0)
	 {
	 	selection.setText("");
	 }
	 }
	}

Các bạn xem giải thích dưới:

gr13

- Bạn thấy đó Android.R.layout.simple_spinner_item dùng để hiển thị phần tử bạn chọn lên spinner. Tương tự như trong ListView bạn có thể custom theo ý mình.

- Dòng lệnh dưới Android.R.layout.simple_list_item_single_choice để hiện thị danh sách các phần tử trong Spinner khi bạn nhấn vào xem Spinner. Bạn phải gọi hàm setDropDownViewResource nếu không nó sẽ lỗi chương trình khi bạn nhấn vào xem. Bạn có thể dùng layout khác nhau, chẳng hạn bạn có thể thay thế bằng Android.R.layout.simple_spinner_dropdown_item.