Created
September 24, 2017 00:25
-
-
Save gavilanch/aa2863e805cea50aac2f954ddce00ec9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NewsListRow.axml | |
<?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:id="@+id/newsListRow_RelativeLayout" | |
android:background="@color/listitemunselected"> | |
<TextView | |
android:text="Small Text" | |
android:textAppearance="?android:attr/textAppearanceSmall" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_toLeftOf="@id/newsImage" | |
android:layout_alignParentLeft="true" | |
android:textStyle="bold" | |
android:layout_marginLeft="5dp" | |
android:layout_marginTop="5dp" | |
android:id="@+id/newsTitle" /> | |
<ImageView | |
android:src="@android:drawable/ic_menu_gallery" | |
android:layout_width="100dp" | |
android:layout_height="100dp" | |
android:layout_alignParentRight="true" | |
android:layout_alignParentTop="true" | |
android:layout_marginLeft="15dp" | |
android:layout_marginRight="15dp" | |
android:id="@+id/newsImage" /> | |
</RelativeLayout> | |
// Colors.xml | |
<?xml version="1.0" encoding="utf-8"?> | |
<resources> | |
<color name="listitemselected">#78909c</color> | |
<color name="listitemunselected">#303030</color> | |
</resources> | |
// ISelectedChecker | |
internal interface ISelectedChecker | |
{ | |
bool IsItemSelected(int id); | |
} | |
// BasesNewsListFragment.cs | |
public class BaseNewsListFragment : Fragment, ISelectedChecker | |
{ | |
protected ListView _newsListView; | |
protected List<News> _news; | |
protected List<News> _selectedNews; | |
private NewsListAdapter _newsListAdapter; | |
public BaseNewsListFragment() | |
{ | |
_news = new List<News>(); | |
_selectedNews = new List<News>(); | |
} | |
public override void OnCreate(Bundle savedInstanceState) | |
{ | |
_selectedNews.Clear(); | |
base.OnCreate(savedInstanceState); | |
SetHasOptionsMenu(true); | |
} | |
protected void SetupFragment() | |
{ | |
SetupViews(); | |
SetupEvents(); | |
SetupAdapter(); | |
} | |
protected void SetupAdapter() | |
{ | |
_newsListAdapter = new NewsListAdapter(Activity, _news, this); | |
_newsListView.Adapter = _newsListAdapter; | |
} | |
protected void SetupViews() | |
{ | |
_newsListView = View.FindViewById<ListView>(Resource.Id.newsListView); | |
} | |
protected void SetupEvents() | |
{ | |
_newsListView.ItemClick += NewsListView_ItemClick; | |
_newsListView.ItemLongClick += _newsListView_ItemLongClick; | |
} | |
private void _newsListView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e) | |
{ | |
int id = (int)e.Id; | |
View view = e.View; | |
RelativeLayout rl = view.FindViewById<RelativeLayout>(Resource.Id.newsListRow_RelativeLayout); | |
if (_selectedNews.Select(x => x.Id).Contains(id)) | |
{ | |
// deselect element | |
var colorForUnselected = Resources.GetString(Resource.Color.listitemunselected); | |
rl.SetBackgroundColor(Android.Graphics.Color.ParseColor(colorForUnselected)); | |
_selectedNews.Remove(_newsListAdapter[e.Position]); | |
} | |
else | |
{ | |
// select element | |
var colorForSelected = Resources.GetString(Resource.Color.listitemselected); | |
rl.SetBackgroundColor(Android.Graphics.Color.ParseColor(colorForSelected)); | |
_selectedNews.Add(_newsListAdapter[e.Position]); | |
} | |
// Forces android to execute OnCreateOptionsMenu | |
Activity.InvalidateOptionsMenu(); | |
} | |
private void NewsListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e) | |
{ | |
var intent = new Intent(Activity, typeof(MainActivity)); | |
var id = (int)e.Id; | |
intent.PutExtra(MainActivity.KEY_ID, id); | |
StartActivity(intent); | |
} | |
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) | |
{ | |
return inflater.Inflate(Resource.Layout.NewsListFragment, container, false); | |
} | |
protected void UnselectElements() | |
{ | |
int count = _newsListView.ChildCount; | |
for (int i = 0; i < count; i++) | |
{ | |
View row = _newsListView.GetChildAt(i); | |
var rl = row.FindViewById<RelativeLayout>(Resource.Id.newsListRow_RelativeLayout); | |
var color = Resources.GetString(Resource.Color.listitemunselected); | |
rl.SetBackgroundColor(Android.Graphics.Color.ParseColor(color)); | |
} | |
} | |
public bool IsItemSelected(int id) | |
{ | |
return _selectedNews.Select(x => x.Id).Contains(id); | |
} | |
} | |
// AllNewsListFragment | |
public class AllNewsListFragment : BaseNewsListFragment | |
{ | |
private NewsService _newsService; | |
public AllNewsListFragment() | |
{ | |
_newsService = new NewsService(); | |
} | |
public override void OnActivityCreated(Bundle savedInstanceState) | |
{ | |
base.OnActivityCreated(savedInstanceState); | |
if (!_news.Any()) | |
{ | |
_news = _newsService.GetNews(); | |
} | |
SetupFragment(); | |
} | |
public override void OnCreateOptionsMenu(IMenu menu, MenuInflater inflater) | |
{ | |
if (_selectedNews.Count > 0) | |
{ | |
inflater.Inflate(Resource.Menu.newsActionMenu, menu); | |
} | |
base.OnCreateOptionsMenu(menu, inflater); | |
} | |
public override bool OnOptionsItemSelected(IMenuItem item) | |
{ | |
switch (item.ItemId) | |
{ | |
case Resource.Id.action_read_later: | |
SaveSelectedNews(_selectedNews); | |
return true; | |
default: | |
return base.OnOptionsItemSelected(item); | |
} | |
} | |
private void SaveSelectedNews(List<News> selectedNews) | |
{ | |
try | |
{ | |
var newsLocalService = new NewsLocalService(); | |
foreach (var news in selectedNews) | |
{ | |
newsLocalService.Save(news); | |
} | |
Toast.MakeText(Activity, $"{selectedNews.Count} news saved", ToastLength.Short).Show(); | |
selectedNews.Clear(); | |
Activity.InvalidateOptionsMenu(); | |
UnselectElements(); | |
} | |
catch (Exception ex) | |
{ | |
Toast.MakeText(Activity, ex.Message, ToastLength.Short).Show(); | |
} | |
} | |
} | |
// SavedNewsListFragment | |
public class SavedNewsListFragment : BaseNewsListFragment | |
{ | |
private NewsLocalService _newsLocalService; | |
public SavedNewsListFragment() | |
{ | |
_newsLocalService = new NewsLocalService(); | |
} | |
public override void OnActivityCreated(Bundle savedInstanceState) | |
{ | |
base.OnActivityCreated(savedInstanceState); | |
FillNews(); | |
SetupFragment(); | |
} | |
private void FillNews() | |
{ | |
_news = _newsLocalService.GetAllSavedForReadLater(); | |
} | |
public override void OnCreateOptionsMenu(IMenu menu, MenuInflater inflater) | |
{ | |
if (_selectedNews.Count > 0) | |
{ | |
inflater.Inflate(Resource.Menu.savedNewsActionMenu, menu); | |
} | |
base.OnCreateOptionsMenu(menu, inflater); | |
} | |
public override bool OnOptionsItemSelected(IMenuItem item) | |
{ | |
switch (item.ItemId) | |
{ | |
case Resource.Id.delete_saved_news: | |
DeleteSelectedNews(_selectedNews); | |
return true; | |
default: | |
return base.OnOptionsItemSelected(item); | |
} | |
} | |
private void DeleteSelectedNews(List<News> selectedNews) | |
{ | |
try | |
{ | |
foreach (var news in selectedNews) | |
{ | |
_newsLocalService.Delete(news.Id); | |
} | |
Toast.MakeText(Activity, $"{selectedNews.Count} news deleted", ToastLength.Short).Show(); | |
selectedNews.Clear(); | |
FillNews(); | |
SetupAdapter(); | |
Activity.InvalidateOptionsMenu(); | |
} | |
catch (Exception ex) | |
{ | |
Toast.MakeText(Activity, ex.Message, ToastLength.Long).Show(); | |
} | |
} | |
} | |
// NewsListAdapter | |
class NewsListAdapter : BaseAdapter<News> | |
{ | |
private Activity _context; | |
private List<News> _news; | |
private ISelectedChecker _selectedChecker; | |
public NewsListAdapter(Activity context, List<News> news, ISelectedChecker selectedChecker) | |
{ | |
_context = context; | |
_news = news; | |
_selectedChecker = selectedChecker; | |
} | |
public override News this[int position] => _news[position]; | |
public override int Count => _news.Count; | |
public override long GetItemId(int position) | |
{ | |
return this[position].Id; | |
} | |
public override View GetView(int position, View convertView, ViewGroup parent) | |
{ | |
var item = this[position]; | |
if (convertView == null) | |
{ | |
convertView = _context.LayoutInflater.Inflate(Resource.Layout.NewsListRow, null); | |
} | |
else | |
{ | |
var id = (int)GetItemId(position); | |
RelativeLayout rl = convertView.FindViewById<RelativeLayout>(Resource.Id.newsListRow_RelativeLayout); | |
if (_selectedChecker.IsItemSelected(id)) | |
{ | |
var colorForSelected = _context.Resources.GetString(Resource.Color.listitemselected); | |
rl.SetBackgroundColor(Android.Graphics.Color.ParseColor(colorForSelected)); | |
} | |
else | |
{ | |
var colorForUnselected = _context.Resources.GetString(Resource.Color.listitemunselected); | |
rl.SetBackgroundColor(Android.Graphics.Color.ParseColor(colorForUnselected)); | |
} | |
} | |
convertView.FindViewById<TextView>(Resource.Id.newsTitle).Text = item.Title; | |
var newsImage = convertView.FindViewById<ImageView>(Resource.Id.newsImage); | |
var imageURL = string.Concat(ValuesService.ImagesBaseURL, item.ImageName); | |
Picasso.With(_context) | |
.Load(imageURL) | |
.Placeholder(_context.GetDrawable(Resource.Drawable.Icon)) | |
.Into(newsImage); | |
return convertView; | |
} | |
} | |
// savedNewsActionMenu | |
<?xml version="1.0" encoding="utf-8" ?> | |
<!--For all properties see: http://developer.android.com/guide/topics/resources/menu-resource.html--> | |
<menu xmlns:android="http://schemas.android.com/apk/res/android"> | |
<item android:id="@+id/delete_saved_news" | |
android:showAsAction="always" | |
android:icon="@android:drawable/ic_delete" /> | |
</menu> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment