From 49102b222c11ca6d13619c71d26801f64eb152d1 Mon Sep 17 00:00:00 2001 From: Tlaster Date: Mon, 4 Jan 2016 14:35:05 +0800 Subject: [PATCH] version 1.2 --- .../{ => Activity}/DetailActivity.cs | 45 +- .../{ => Activity}/MainActivity.cs | 86 +- .../Adapter/DetailListAdapter.cs | 54 +- AnimateRaw.Android/Adapter/MainListAdapter.cs | 52 +- AnimateRaw.Android/AnimateRaw.Android.csproj | 25 +- .../Resources/Resource.Designer.cs | 5059 +---------------- .../Resources/drawable/SplashScreen.png | Bin 0 -> 30370 bytes .../Resources/layout/DetailListLayout.axml | 25 + .../Resources/layout/MainPage.axml | 11 +- AnimateRaw.Android/View/ExRecyclerView.cs | 63 + .../ScrollChildSwipeRefreshLayout.cs | 0 .../ViewHolder/DetailViewHolder.cs | 30 + .../ViewHolder/MainViewHolder.cs | 29 + AnimateRaw.Android/packages.config | 3 +- AnimateRaw.Shared/Helper/FavorHelper.cs | 31 + AnimateRaw.Shared/Model/AnimateListModel.cs | 8 +- AnimateRaw.Shared/Model/AnimateSetModel.cs | 1 + AnimateRaw/AnimateRaw.csproj | 17 +- .../AnimateListIncrementalLoadingClass.cs | 45 + .../GeneratorIncrementalLoadingClass.cs | 40 + AnimateRaw/Common/IncrementalLoadingBase.cs | 155 + AnimateRaw/Package.appxmanifest | 6 +- AnimateRaw/Strings/en-US/Resources.resw | 126 + AnimateRaw/Strings/zh-CN/Resources.resw | 126 + AnimateRaw/{ => View}/AnimateDetailPage.xaml | 45 +- .../{ => View}/AnimateDetailPage.xaml.cs | 0 AnimateRaw/{ => View}/AnimatePlayPage.xaml | 0 AnimateRaw/{ => View}/AnimatePlayPage.xaml.cs | 0 AnimateRaw/{ => View}/MainPage.xaml | 42 +- AnimateRaw/{ => View}/MainPage.xaml.cs | 0 .../ViewModel/AnimateDetailViewModel.cs | 12 +- AnimateRaw/ViewModel/MainViewModel.cs | 65 +- 32 files changed, 1108 insertions(+), 5093 deletions(-) rename AnimateRaw.Android/{ => Activity}/DetailActivity.cs (83%) rename AnimateRaw.Android/{ => Activity}/MainActivity.cs (51%) create mode 100644 AnimateRaw.Android/Resources/drawable/SplashScreen.png create mode 100644 AnimateRaw.Android/Resources/layout/DetailListLayout.axml create mode 100644 AnimateRaw.Android/View/ExRecyclerView.cs rename AnimateRaw.Android/{ => View}/ScrollChildSwipeRefreshLayout.cs (100%) create mode 100644 AnimateRaw.Android/ViewHolder/DetailViewHolder.cs create mode 100644 AnimateRaw.Android/ViewHolder/MainViewHolder.cs create mode 100644 AnimateRaw/Common/AnimateListIncrementalLoadingClass.cs create mode 100644 AnimateRaw/Common/GeneratorIncrementalLoadingClass.cs create mode 100644 AnimateRaw/Common/IncrementalLoadingBase.cs create mode 100644 AnimateRaw/Strings/en-US/Resources.resw create mode 100644 AnimateRaw/Strings/zh-CN/Resources.resw rename AnimateRaw/{ => View}/AnimateDetailPage.xaml (56%) rename AnimateRaw/{ => View}/AnimateDetailPage.xaml.cs (100%) rename AnimateRaw/{ => View}/AnimatePlayPage.xaml (100%) rename AnimateRaw/{ => View}/AnimatePlayPage.xaml.cs (100%) rename AnimateRaw/{ => View}/MainPage.xaml (93%) rename AnimateRaw/{ => View}/MainPage.xaml.cs (100%) diff --git a/AnimateRaw.Android/DetailActivity.cs b/AnimateRaw.Android/Activity/DetailActivity.cs similarity index 83% rename from AnimateRaw.Android/DetailActivity.cs rename to AnimateRaw.Android/Activity/DetailActivity.cs index e1ed9bb..97404bf 100644 --- a/AnimateRaw.Android/DetailActivity.cs +++ b/AnimateRaw.Android/Activity/DetailActivity.cs @@ -19,6 +19,7 @@ using System.Net; using System; using System.Threading.Tasks; +using Android.Support.V7.Widget; namespace AnimateRaw.Android { @@ -26,7 +27,7 @@ namespace AnimateRaw.Android public class DetailActivity : Activity { private double _id; - private ListView _listView; + private ExRecyclerView _exRecyclerView; private string _name; private ScrollChildSwipeRefreshLayout _refresher; @@ -52,8 +53,8 @@ protected override async void OnCreate(Bundle savedInstanceState) } SetContentView(Resource.Layout.MainPage); - _listView = FindViewById(Resource.Id.MainPageListView); - _listView.ItemClick += listView_ItemClick; + _exRecyclerView = FindViewById(Resource.Id.MainPageRecyclerView); + _exRecyclerView.ViewLayoutManager = new GridLayoutManager(this, 3); _refresher = FindViewById(Resource.Id.MainPageRefresher); _refresher.SetColorSchemeResources(Resource.Color.MediumVioletRed); _refresher.Refresh += refresher_Refresh; @@ -66,37 +67,24 @@ private async void refresher_Refresh(object sender, EventArgs e) await Refresh(); } - private async void listView_ItemClick(object sender, AdapterView.ItemClickEventArgs e) - { - var item = (_listView.Adapter as DetailListAdapter).Items[e.Position]; - try - { - using (var client = new HttpClient()) - await client.GetStringAsync($"http://tlaster.me/getanimate?id={_id}&filename={item.FileName}"); - } - catch - { - } - var intent = new Intent(Intent.ActionView); - intent.SetDataAndType(global::Android.Net.Uri.Parse(item.FilePath), "video/mp4"); - StartActivity(intent); - } - private async Task Refresh() { try { using (var client = new HttpClient()) { - var jsstr = await client.GetStringAsync($"http://tlaster.me/getanimate?id={_id}"); + var jsstr = await client.GetStringAsync($"http://tlaster.me/api/detail?id={_id}"); var list = (from item in (JArray)((JObject)JsonConvert.DeserializeObject(jsstr))["SetList"] select new AnimateSetModel { ClickCount = item.Value("ClickCount"), FileName = item.Value("FileName"), FilePath = item.Value("FilePath"), + FileThumb = item.Value("FileThumb"), }).OrderBy(a => a.FileName).ToList(); - _listView.Adapter = new DetailListAdapter(this, list); + var ada = new DetailListAdapter(this, list); + ada.ItemClick += Ada_ItemClick; + _exRecyclerView.ViewAdapter = ada; _refresher.Refreshing = false; } } @@ -107,5 +95,20 @@ private async Task Refresh() } } + private async void Ada_ItemClick(object sender, int e) + { + var item = (_exRecyclerView.ViewAdapter as DetailListAdapter).Items[e]; + try + { + using (var client = new HttpClient()) + await client.GetStringAsync($"http://tlaster.me/api/detail?id={_id}&filename={item.FileName}"); + } + catch + { + } + var intent = new Intent(Intent.ActionView); + intent.SetDataAndType(global::Android.Net.Uri.Parse(item.FilePath), "video/mp4"); + StartActivity(intent); + } } } \ No newline at end of file diff --git a/AnimateRaw.Android/MainActivity.cs b/AnimateRaw.Android/Activity/MainActivity.cs similarity index 51% rename from AnimateRaw.Android/MainActivity.cs rename to AnimateRaw.Android/Activity/MainActivity.cs index fb40670..5e7f7b2 100644 --- a/AnimateRaw.Android/MainActivity.cs +++ b/AnimateRaw.Android/Activity/MainActivity.cs @@ -15,14 +15,20 @@ using Android.Graphics; using Android.Support.V4.Widget; using System.Net; +using System.Collections.ObjectModel; +using Android.Support.V7.Widget; namespace AnimateRaw.Android { [Activity(Label = "Animate Raw", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { - private ListView _listView; + private ExRecyclerView _recyclerView; private SwipeRefreshLayout _refresher; + private bool _isLoading; + private int _page = 0; + private bool _hasMore = true; + private LinearLayoutManager _layoutManager; protected override async void OnCreate(Bundle bundle) { @@ -43,8 +49,10 @@ protected override async void OnCreate(Bundle bundle) } base.OnCreate(bundle); SetContentView(Resource.Layout.MainPage); - _listView = FindViewById(Resource.Id.MainPageListView); - _listView.ItemClick += listView_ItemClick; + _recyclerView = FindViewById(Resource.Id.MainPageRecyclerView); + _recyclerView.OnScroll += recyclerView_OnScroll; + _layoutManager = new LinearLayoutManager(this); + _recyclerView.ViewLayoutManager = _layoutManager; _refresher = FindViewById(Resource.Id.MainPageRefresher); _refresher.SetColorSchemeResources(Resource.Color.MediumVioletRed); _refresher.Refresh += refresher_Refresh; @@ -52,16 +60,45 @@ protected override async void OnCreate(Bundle bundle) await Refresh(); } - private void listView_ItemClick(object sender, AdapterView.ItemClickEventArgs e) + private void recyclerView_OnScroll(object sender, OnScrollEventArgs e) { - var item = (_listView.Adapter as MainListAdapter).Items[e.Position]; - var intent = new Intent(this, typeof(DetailActivity)); - Bundle bundle = new Bundle(); - bundle.PutString("name", item.Name); - bundle.PutDouble("id", item.ID); - intent.PutExtras(bundle); - StartActivity(intent); + if (e.dy > 0) + { + var visibleItemCount = _layoutManager.ChildCount; + var totalItemCount = _layoutManager.ItemCount; + var pastVisiblesItems = _layoutManager.FindFirstVisibleItemPosition(); + + if (!_isLoading) + { + if ((visibleItemCount + pastVisiblesItems) >= totalItemCount - 3) + { + _isLoading = true; + LoadMore(); + } + } + } + } + + + private async void LoadMore() + { + using (var client = new HttpClient()) + { + var jsstr = await client.GetStringAsync($"http://tlaster.me/api/list?page={_page++}"); + var obj = (JObject)JsonConvert.DeserializeObject(jsstr); + _hasMore = (bool)obj["HasMore"]; + var list = (from item in (JArray)obj["List"] + select new AnimateListModel + { + ID = item.Value("ID"), + Name = item.Value("Name"), + LastUpdateBeijing = DateTime.Parse(item.Value("LastUpdate")), + }).ToList(); + (_recyclerView.ViewAdapter as MainListAdapter).Add(list); + _isLoading = false; + } } + private async void refresher_Refresh(object sender, EventArgs e) { @@ -74,16 +111,20 @@ private async System.Threading.Tasks.Task Refresh() { using (var client = new HttpClient()) { - var jsstr = await client.GetStringAsync("http://tlaster.me/getanimate"); - - var list = (from item in (JArray)JsonConvert.DeserializeObject(jsstr) + _page = 0; + var jsstr = await client.GetStringAsync($"http://tlaster.me/api/list?page={_page++}"); + var obj = (JObject)JsonConvert.DeserializeObject(jsstr); + _hasMore = (bool)obj["HasMore"]; + var list = (from item in (JArray)obj["List"] select new AnimateListModel { ID = item.Value("ID"), Name = item.Value("Name"), - LastUpdate = TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("China Standard Time")) - DateTime.Parse(item.Value("LastUpdate")), - }).OrderBy(a => a.LastUpdate).ToList(); - _listView.Adapter = new MainListAdapter(this, list); + LastUpdateBeijing = DateTime.Parse(item.Value("LastUpdate")), + }).ToList(); + var ada = new MainListAdapter(this, list); + ada.ItemClick += Ada_ItemClick; + _recyclerView.ViewAdapter = ada; _refresher.Refreshing = false; } } @@ -93,6 +134,17 @@ private async System.Threading.Tasks.Task Refresh() _refresher.Refreshing = false; } } + + private void Ada_ItemClick(object sender, int e) + { + var item = (_recyclerView.ViewAdapter as MainListAdapter).Items[e]; + var intent = new Intent(this, typeof(DetailActivity)); + Bundle bundle = new Bundle(); + bundle.PutString("name", item.Name); + bundle.PutDouble("id", item.ID); + intent.PutExtras(bundle); + StartActivity(intent); + } } } diff --git a/AnimateRaw.Android/Adapter/DetailListAdapter.cs b/AnimateRaw.Android/Adapter/DetailListAdapter.cs index a022707..5850734 100644 --- a/AnimateRaw.Android/Adapter/DetailListAdapter.cs +++ b/AnimateRaw.Android/Adapter/DetailListAdapter.cs @@ -10,11 +10,16 @@ using Android.Views; using Android.Widget; using AnimateRaw.Shared.Model; +using Android.Support.V7.Widget; +using AnimateRaw.Android.ViewHolder; +using Android.Graphics; +using System.Net.Http; namespace AnimateRaw.Android.Adapter { - public class DetailListAdapter : BaseAdapter + public class DetailListAdapter : RecyclerView.Adapter { + public event EventHandler ItemClick; public List Items { get; private set; } private Activity _context; public DetailListAdapter(Activity context, List items) : base() @@ -26,23 +31,46 @@ public override long GetItemId(int position) { return position; } - public override AnimateSetModel this[int position] + + public override int ItemCount => Items.Count; + + public override async void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) { - get { return Items[position]; } + DetailViewHolder vh = holder as DetailViewHolder; + vh.Name.Text = Items[position].FileName; + vh.ClickCount.Text = $"Click Count:{Items[position].ClickCount}"; + if (string.IsNullOrEmpty(Items[position].FileThumb)) + { + vh.Image.SetBackgroundColor(Color.MediumVioletRed); + vh.Image.SetImageResource(Resource.Drawable.SplashScreen); + } + else + { + + vh.Image.SetImageBitmap(await GetImageBitmapFromUrl(Items[position].FileThumb)); + } } - public override int Count + private async System.Threading.Tasks.Task GetImageBitmapFromUrl(string url) { - get { return Items.Count; } + Bitmap imageBitmap = null; + using (var client = new HttpClient()) + { + var imageBytes = await client.GetByteArrayAsync(url); + if (imageBytes != null && imageBytes.Length > 0) + { + imageBitmap = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length); + } + } + return imageBitmap; } - public override View GetView(int position, View convertView, ViewGroup parent) + + public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { - View view = convertView; - if (view == null) - view = _context.LayoutInflater.Inflate(Resource.Layout.MainListLayout, null); - view.FindViewById(Resource.Id.MainListLayoutName).Text = Items[position].FileName; - view.FindViewById(Resource.Id.MainListLayoutUpdateTime).Text = $"Click Count:{Items[position].ClickCount}"; - return view; + View itemView = LayoutInflater.From(parent.Context). + Inflate(Resource.Layout.DetailListLayout, parent, false); + DetailViewHolder vh = new DetailViewHolder(itemView); + itemView.Click += (s, e) => ItemClick?.Invoke(s, vh.LayoutPosition); + return vh; } - } } \ No newline at end of file diff --git a/AnimateRaw.Android/Adapter/MainListAdapter.cs b/AnimateRaw.Android/Adapter/MainListAdapter.cs index e409740..7081377 100644 --- a/AnimateRaw.Android/Adapter/MainListAdapter.cs +++ b/AnimateRaw.Android/Adapter/MainListAdapter.cs @@ -10,39 +10,31 @@ using Android.Views; using Android.Widget; using AnimateRaw.Shared.Model; +using System.Collections.ObjectModel; +using Android.Support.V7.Widget; namespace AnimateRaw.Android.Adapter { - public class MainListAdapter : BaseAdapter + public class MainListAdapter : RecyclerView.Adapter { + public event EventHandler ItemClick; + public List Items { get; private set; } private Activity _context; public MainListAdapter(Activity context, List items) : base() { - this._context = context; - this.Items = items; - } - public override long GetItemId(int position) - { - return position; - } - public override AnimateListModel this[int position] - { - get { return Items[position]; } - } - public override int Count - { - get { return Items.Count; } + _context = context; + Items = items; } - public override View GetView(int position, View convertView, ViewGroup parent) + public void Add(List list) { - View view = convertView; - if (view == null) - view = _context.LayoutInflater.Inflate(Resource.Layout.MainListLayout, null); - view.FindViewById(Resource.Id.MainListLayoutName).Text = Items[position].Name; - view.FindViewById(Resource.Id.MainListLayoutUpdateTime).Text = GetUpdate(Items[position].LastUpdate); - return view; + Items.AddRange(list); + NotifyDataSetChanged(); } + public override long GetItemId(int position) => position; + + public override int ItemCount => Items.Count; + private string GetUpdate(TimeSpan time) { if (time.Days != 0) @@ -59,5 +51,21 @@ private string GetUpdate(TimeSpan time) } return "Just now"; } + + public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position) + { + MainViewHolder vh = holder as MainViewHolder; + vh.Name.Text = Items[position].Name; + vh.UpdateTime.Text = GetUpdate(Items[position].LastUpdate); + } + + public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) + { + View itemView = LayoutInflater.From(parent.Context). + Inflate(Resource.Layout.MainListLayout, parent, false); + MainViewHolder vh = new MainViewHolder(itemView); + itemView.Click += (s, e) => ItemClick?.Invoke(s, vh.LayoutPosition); + return vh; + } } } \ No newline at end of file diff --git a/AnimateRaw.Android/AnimateRaw.Android.csproj b/AnimateRaw.Android/AnimateRaw.Android.csproj index 71deb28..487f68e 100644 --- a/AnimateRaw.Android/AnimateRaw.Android.csproj +++ b/AnimateRaw.Android/AnimateRaw.Android.csproj @@ -45,22 +45,27 @@ + + ..\packages\Xamarin.Android.Support.v4.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll + - ..\packages\Newtonsoft.Json.7.0.1\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.8.0.1\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll - - ..\packages\Xamarin.Android.Support.v4.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll - True + + ..\packages\Xamarin.Android.Support.v7.RecyclerView.23.1.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll - - + + + + + - + @@ -72,6 +77,9 @@ AndroidResource + + AndroidResource + @@ -85,6 +93,9 @@ + + + + + - + + AnimateDetailPage.xaml - + AnimatePlayPage.xaml App.xaml + + - + MainPage.xaml @@ -137,15 +142,15 @@ MSBuild:Compile Designer - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + MSBuild:Compile Designer diff --git a/AnimateRaw/Common/AnimateListIncrementalLoadingClass.cs b/AnimateRaw/Common/AnimateListIncrementalLoadingClass.cs new file mode 100644 index 0000000..2608016 --- /dev/null +++ b/AnimateRaw/Common/AnimateListIncrementalLoadingClass.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using AnimateRaw.Shared.Model; +using System.Net.Http; +using Windows.Data.Json; +using AnimateRaw.Extension; + +namespace AnimateRaw.Common +{ + public class AnimateListIncrementalLoadingClass : IncrementalLoadingBase + { + private bool _hasMore = true; + private int _page = 0; + + protected override bool HasMoreItemsOverride() => _hasMore; + + protected override async Task> LoadMoreItemsOverrideAsync(CancellationToken c, uint count) + { + using (var client = new HttpClient()) + { + var jsstr = await client.GetStringAsync($"http://tlaster.me/api/list?page={_page++}"); + var obj = JsonObject.Parse(jsstr); + _hasMore = obj.GetNamedBoolean("HasMore"); + if (obj.GetNamedBoolean("Success")) + { + return (from item in obj.GetNamedArray("List") + select new AnimateListModel + { + ID = item.GetNamedNumber("ID"), + Name = item.GetNamedString("Name"), + LastUpdateBeijing = DateTime.Parse(item.GetNamedString("LastUpdate")), + }).ToArray(); + } + else + { + return null; + } + } + } + } +} diff --git a/AnimateRaw/Common/GeneratorIncrementalLoadingClass.cs b/AnimateRaw/Common/GeneratorIncrementalLoadingClass.cs new file mode 100644 index 0000000..17b65fb --- /dev/null +++ b/AnimateRaw/Common/GeneratorIncrementalLoadingClass.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AnimateRaw.Common +{ + public class GeneratorIncrementalLoadingClass : IncrementalLoadingBase + { + public GeneratorIncrementalLoadingClass(uint maxCount, Func generator) + { + _generator = generator; + _maxCount = maxCount; + } + + protected async override Task> LoadMoreItemsOverrideAsync(CancellationToken c, uint count) + { + uint toGenerate = Math.Min(count, _maxCount - _count); + var values = from j in Enumerable.Range((int)_count, (int)toGenerate) + select (object)_generator(j); + _count += toGenerate; + return await Task.FromResult>(values.ToArray()); + } + + protected override bool HasMoreItemsOverride() + { + return _count < _maxCount; + } + + #region State + + Func _generator; + uint _count = 0; + uint _maxCount; + + #endregion + } +} diff --git a/AnimateRaw/Common/IncrementalLoadingBase.cs b/AnimateRaw/Common/IncrementalLoadingBase.cs new file mode 100644 index 0000000..48566ec --- /dev/null +++ b/AnimateRaw/Common/IncrementalLoadingBase.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.UI.Xaml.Data; + +namespace AnimateRaw.Common +{ + public abstract class IncrementalLoadingBase : IList, ISupportIncrementalLoading, INotifyCollectionChanged + { + #region IList + + public int Add(object value) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(object value) => _storage.Contains(value); + + public int IndexOf(object value) => _storage.IndexOf(value); + + public void Insert(int index, object value) + { + throw new NotImplementedException(); + } + + public bool IsFixedSize => false; + + public bool IsReadOnly => true; + + public void Remove(object value) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public object this[int index] + { + get + { + return _storage[index]; + } + set + { + throw new NotImplementedException(); + } + } + + public void CopyTo(Array array, int index) => ((IList)_storage).CopyTo(array, index); + + public int Count => _storage.Count; + + public bool IsSynchronized => false; + + public object SyncRoot + { + get { throw new NotSupportedException(); } + } + + public IEnumerator GetEnumerator() => _storage.GetEnumerator(); + + #endregion + + #region ISupportIncrementalLoading + + public bool HasMoreItems => HasMoreItemsOverride(); + + public IAsyncOperation LoadMoreItemsAsync(uint count) + { + if (_busy) + { + throw new InvalidOperationException("Only one operation in flight at a time"); + } + + _busy = true; + + return AsyncInfo.Run((c) => LoadMoreItemsAsync(c, count)); + } + + #endregion + + #region INotifyCollectionChanged + + public event NotifyCollectionChangedEventHandler CollectionChanged; + + #endregion + + #region Private methods + + async Task LoadMoreItemsAsync(CancellationToken c, uint count) + { + try + { + var items = await LoadMoreItemsOverrideAsync(c, count); + var baseIndex = _storage.Count; + + _storage.AddRange(items); + + // Now notify of the new items + NotifyOfInsertedItems(baseIndex, items.Count); + + return new LoadMoreItemsResult { Count = (uint)items.Count }; + } + finally + { + _busy = false; + } + } + + void NotifyOfInsertedItems(int baseIndex, int count) + { + if (CollectionChanged == null) + { + return; + } + + for (int i = 0; i < count; i++) + { + var args = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, _storage[i + baseIndex], i + baseIndex); + CollectionChanged(this, args); + } + } + + #endregion + + #region Overridable methods + + protected abstract Task> LoadMoreItemsOverrideAsync(CancellationToken c, uint count); + protected abstract bool HasMoreItemsOverride(); + + #endregion + + #region State + + List _storage = new List(); + bool _busy = false; + + #endregion + } +} diff --git a/AnimateRaw/Package.appxmanifest b/AnimateRaw/Package.appxmanifest index 54f5a01..0804a15 100644 --- a/AnimateRaw/Package.appxmanifest +++ b/AnimateRaw/Package.appxmanifest @@ -1,9 +1,9 @@  - + - Animate Raw(BETA) + Animate Raw Tlaster Assets\StoreLogo.png @@ -15,7 +15,7 @@ - + diff --git a/AnimateRaw/Strings/en-US/Resources.resw b/AnimateRaw/Strings/en-US/Resources.resw new file mode 100644 index 0000000..89f891f --- /dev/null +++ b/AnimateRaw/Strings/en-US/Resources.resw @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Favor + + + Raws + + \ No newline at end of file diff --git a/AnimateRaw/Strings/zh-CN/Resources.resw b/AnimateRaw/Strings/zh-CN/Resources.resw new file mode 100644 index 0000000..d05bbe8 --- /dev/null +++ b/AnimateRaw/Strings/zh-CN/Resources.resw @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 收藏 + + + 列表 + + \ No newline at end of file diff --git a/AnimateRaw/AnimateDetailPage.xaml b/AnimateRaw/View/AnimateDetailPage.xaml similarity index 56% rename from AnimateRaw/AnimateDetailPage.xaml rename to AnimateRaw/View/AnimateDetailPage.xaml index 6a2ef08..2845958 100644 --- a/AnimateRaw/AnimateDetailPage.xaml +++ b/AnimateRaw/View/AnimateDetailPage.xaml @@ -9,6 +9,8 @@ xmlns:converter="using:AnimateRaw.Converter" mc:Ignorable="d"> + + @@ -35,21 +37,36 @@ - - - - - + + - - - - + + + + + + + + + + + Click Count: + + + - - - + + + + + + + + + + diff --git a/AnimateRaw/AnimateDetailPage.xaml.cs b/AnimateRaw/View/AnimateDetailPage.xaml.cs similarity index 100% rename from AnimateRaw/AnimateDetailPage.xaml.cs rename to AnimateRaw/View/AnimateDetailPage.xaml.cs diff --git a/AnimateRaw/AnimatePlayPage.xaml b/AnimateRaw/View/AnimatePlayPage.xaml similarity index 100% rename from AnimateRaw/AnimatePlayPage.xaml rename to AnimateRaw/View/AnimatePlayPage.xaml diff --git a/AnimateRaw/AnimatePlayPage.xaml.cs b/AnimateRaw/View/AnimatePlayPage.xaml.cs similarity index 100% rename from AnimateRaw/AnimatePlayPage.xaml.cs rename to AnimateRaw/View/AnimatePlayPage.xaml.cs diff --git a/AnimateRaw/MainPage.xaml b/AnimateRaw/View/MainPage.xaml similarity index 93% rename from AnimateRaw/MainPage.xaml rename to AnimateRaw/View/MainPage.xaml index 411c874..6848219 100644 --- a/AnimateRaw/MainPage.xaml +++ b/AnimateRaw/View/MainPage.xaml @@ -215,29 +215,27 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - +