[Xamarin] 用ListFragment 製作 List

2016-07-19

之前在 製作過ListActivity (http://no2don.blogspot.tw/2013/07/xamarin-listactivity.html) ,今天我們聊聊使用ListFragment 來製作列表,至於為什麼呢?因為現在官方很多範例都是用ListFragment

Screenshot_20160719-153414

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 記得要去下載
sh053

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/


當麻許的超技八 2014 | Donma Hsu Design.