[Xamarin] 用ListFragment 製作 List
2016-07-19
之前在 製作過ListActivity (http://no2don.blogspot.tw/2013/07/xamarin-listactivity.html) ,今天我們聊聊使用ListFragment 來製作列表,至於為什麼呢?因為現在官方很多範例都是用ListFragment
1. Layout部分 Main.axml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
這裡面有一個FrameLayout 負責拿來放List的資料,然後每一個item 的Layout itemlayout.axml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/linearContainer"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/tvId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#CDFFE7"
android:textSize="20dip"
android:textStyle="italic"
android:text="USERID" />
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#E76DA9"
android:paddingLeft="100dip"
android:text="USERNAME" />
</LinearLayout>
<ImageView
android:id="@+id/imgUser"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/Icon"
android:layout_alignParentRight="true" />
</RelativeLayout>
2.建立MainListFragment ,主要繼承 Android.Support.V4.App.ListFragment 如果沒有取得component 記得要去下載
public class MainListFragment : Android.Support.V4.App.ListFragment
{
private List<UserInfo> datas;
private DListAdapter adapter;
private Activity _Activity;
public override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
public override void OnAttach(Activity activity)
{
base.OnAttach(activity);
//載入假資料
datas = new List<UserInfo>();
for (int i = 1; i <= 10; i++)
{
datas.Add(new UserInfo { Id = i + "", Name = "當麻許" + i, Thumb = "https://scontent-tpe1-1.xx.fbcdn.net/v/t1.0-1/p160x160/12717553_990702884338448_4996131999379625346_n.jpg?oh=08b10033b3195da4c798a155b6a53c4e&oe=58246A46" });
datas.Add(new UserInfo { Id = i + "", Name = "Donma" + i, Thumb = "https://scontent-tpe1-1.xx.fbcdn.net/v/t1.0-1/c12.12.155.155/577256_189686817873269_571470949_n.jpg?oh=e2885725dfe986899f6426aef31bd65a&oe=58331088" });
datas.Add(new UserInfo { Id = i + "", Name = "Grimm" + i, Thumb = "https://scontent-tpe1-1.xx.fbcdn.net/v/t1.0-1/p160x160/11204432_944409652247471_1055773727056515807_n.jpg?oh=bff2eefe683ae75d5cd01cd1ee3dec68&oe=5824D6C7" });
}
adapter = new DListAdapter(activity);
//載入資料
adapter.LoadData(datas);
//將ListFragment 的 ListAdapter 配入
//這一行一定要加入
ListAdapter = adapter;
}
}
其中 我放入了30筆的假資料這裡面有一個Adapter 這配接器 必須繼承 Android.Widget.BaseAdapter
private class DListAdapter : BaseAdapter<UserInfo>
{
List<UserInfo> items;
Activity context;
//暫存圖片下載的任務
ConcurrentDictionary<string, Task<byte[]>> faceCache = new ConcurrentDictionary<string, Task<byte[]>>();
public DListAdapter(Activity context)
: base()
{
this.context = context;
}
public void LoadData(List<UserInfo> items)
{
this.items = items;
NotifyDataSetChanged();
}
public override long GetItemId(int position)
{
return position;
}
//取得每一個item 的view
public override View GetView(int position, View convertView, ViewGroup parent)
{
var view = EnsureView(convertView);
var item = items[position];
var img = view.FindViewById<ImageView>(Resource.Id.imgUser);
var id = view.FindViewById<TextView>(Resource.Id.tvId);
var name = view.FindViewById<TextView>(Resource.Id.tvName);
id.Text = item.Id;
name.Text = item.Name;
FetchImage(item.Thumb, view);
return view;
}
public override int Count
{
get { return items.Count; }
}
public override UserInfo this[int position]
{
get { return items[position]; }
}
//轉換確保為DiscussionView
DiscussionView EnsureView(View convertView)
{
DiscussionView view = convertView as DiscussionView;
if (view == null)
view = new DiscussionView(context);
return view;
}
public override int ViewTypeCount
{
get
{
return 1;
}
}
void FetchImage(string url, DiscussionView view)
{
var data = faceCache.GetOrAdd(url, u => Task.Run(() =>
{
var client = new WebClient();
try
{
return client.DownloadData(u);
}
catch
{
return null;
}
}));
if (data.IsCompleted && data.Result != null)
{
var imgUser = view.FindViewById<ImageView>(Resource.Id.imgUser);
var bmp = BitmapFactory.DecodeByteArray(data.Result, 0, data.Result.Length);
bmp = ResizeBitmap(bmp);
imgUser.SetImageBitmap(bmp);
//imgUser.SetImageDrawable(new VignetteDrawable(bmp, withEffect: false));
GC.Collect();
}
else
{
data.ContinueWith(t =>
{
if (t.Result != null)
{
var bmp = BitmapFactory.DecodeByteArray(data.Result, 0, data.Result.Length);
bmp = ResizeBitmap(bmp);
context.RunOnUiThread(() =>
{
var avatar = view.FindViewById<ImageView>(Resource.Id.imgUser);
avatar.SetImageBitmap(bmp);
});
}
});
GC.Collect();
}
}
//縮圖
Bitmap ResizeBitmap(Bitmap inputBitmap)
{
var size = (int)TypedValue.ApplyDimension(ComplexUnitType.Px, 48, context.Resources.DisplayMetrics);
return Bitmap.CreateScaledBitmap(inputBitmap, size, size, true);
}
}
3.之後再主要的Activity 部分就可以將 MainListFragment 建立起來
listFragment=new MainListFragment();
SupportFragmentManager.BeginTransaction()
.Add(Resource.Id.container, listFragment,"TAG").Commit();
source:
https://www.dropbox.com/s/ow1271lxnz9pf7r/TestListFragment.7z?dl=0
reference:
https://developer.xamarin.com/api/type/Android.App.ListFragment/
https://blog.xamarin.com/android-the-swipe-down-to-refresh-pattern/