I have a listview with a list of items. There is an event that sends the new value for a given row of the listview. For example: I have a listview with the names ("Jhon", "Alice", "Paul", "Mary", "Stive") then the event me "warns" that the name of Jhon was changed to "Josh". How can I access the online listview containing the name "Jhon", I am using adapter and viewholder to populate the listview.
using System;
using Android.App;
using Android.Views;
using Android.Widget;
using MyApp
using Android.Content;
using System.Collections.Generic;
using Android.Graphics;
public class AdapterContatos : BaseAdapter
{
private Activity _Activity = null;
private static Usuario[] _ListaContatos;
private static Grupo[] _Listagrupos;
private static List<Object> _ListaCompleta = new List<object>();
private static LayoutInflater _Inflate = null;
private static View _View;
private static Dictionary<int, Bitmap> _DicAvatarContato = new Dictionary<int, Bitmap>();
private static Dictionary<int, Bitmap> _DicAvatarGrupo = new Dictionary<int, Bitmap>();
public AdapterContatos(Activity activity, Usuario[] listaContatos, Grupo[] listaGrupo)
{
_Activity = activity;
_ListaContatos = listaContatos;
_Listagrupos = listaGrupo;
_ListaCompleta.AddRange(_Listagrupos);
_ListaCompleta.AddRange(_ListaContatos);
try
{
_Inflate = (LayoutInflater)_Activity.GetSystemService(Context.LayoutInflaterService);
foreach (var item in _ListaContatos)
ObtemImagemArredondadaContato(item.Codigo);
foreach (var item in _Listagrupos)
ObtemImagemArredondadaGrupo(item.CodigoDoGrupo);
}
catch (Exception ex)
{
UtilExcessao.TrateExcessao(ex);
}
}
ViewHolderContato _HolderContato;
public override View GetView(int position, View convertView, ViewGroup parent)
{
_View = convertView;
try
{
if (_View != null)
_HolderContato = _View.Tag as ViewHolderContato;
else
{
_View = _Activity.LayoutInflater.Inflate(Resource.Layout.LayoutContato, null);
_HolderContato = CriaViewHolder(position);
}
PopulaViewHolder(_HolderContato, position);
_View.Tag = _HolderContato;
}
catch (Exception ex)
{
UtilExcessao.TrateExcessao(ex);
}
return _View;
}
private ViewHolderContato CriaViewHolder(int position)
{
ViewHolderContato holder = new ViewHolderContato();
holder.txtNome = _View.FindViewById<TextView>(Resource.Id.nomeContato);
holder.txtCargo = _View.FindViewById<TextView>(Resource.Id.funcaoContato);
holder.imgAvatar = _View.FindViewById<ImageView>(Resource.Id.imgAvatar);
holder.txtPrimeiraLetraNomeOuGrupo = _View.FindViewById<TextView>(Resource.Id.txtPrimeiraLetraNomeOuGrupo);
holder.txtQntdMsgNaoLidas = _View.FindViewById<TextView>(Resource.Id.imgAlertaChat);
return holder;
}
private void PopulaViewHolder(ViewHolderContato holder, int position)
{
if(EhGrupo(_ListaCompleta[position]))
PopulaViewHolderGrupo(holder,
(Grupo)_ListaCompleta[position]);
else
PopulaViewHolderUsuario(holder,
(Usuario)_ListaCompleta[position]);
}
void PopulaViewHolderGrupo(ViewHolderContato holder, Grupo grupo)
{
holder.txtNome.Text = grupo.NomeDoGrupo;
holder.txtCargo.Text = UtilFormatacao.ObtenhaNomeIntegrantesGrupoFormatado(grupo.ListaDeUsuarios);
holder.txtPrimeiraLetraNomeOuGrupo.Text = UtilFormatacao.ObtenhaPrimeiraLetraDoNome(grupo.NomeDoGrupo);
MostraAvatargrupo(holder, grupo.CodigoDoGrupo, grupo.NomeDoGrupo);
}
void PopulaViewHolderUsuario(ViewHolderContato holder, Usuario usuario)
{
holder.txtNome.Text = usuario.Nome;
holder.txtCargo.Text = usuario.Cargo;
MostraAvatarContatoPrivado(holder, usuario.Codigo, usuario.Nome);
}
void MostraAvatarContatoPrivado(ViewHolderContato holder, int codigo, string nome)
{
if (_DicAvatarContato[codigo] != null)
{
holder.imgAvatar.SetImageBitmap(_DicAvatarContato[codigo]);
holder.txtPrimeiraLetraNomeOuGrupo.Text = "";
}
else
{
holder.imgAvatar.SetImageResource(Resource.Drawable.icon_avatar_default_52);
holder.txtPrimeiraLetraNomeOuGrupo.Text = UtilFormatacao.ObtenhaPrimeiraLetraDoNome(nome);
}
}
void MostraAvatargrupo(ViewHolderContato holder, int codigoGrupo, string nomeGrupo)
{
if (_DicAvatarGrupo[codigoGrupo] != null)
{
holder.imgAvatar.SetImageBitmap(_DicAvatarGrupo[codigoGrupo]);
holder.txtPrimeiraLetraNomeOuGrupo.Text = "";
}
else
{
holder.imgAvatar.SetImageResource(Resource.Drawable.icon_avatar_default_52);
holder.txtPrimeiraLetraNomeOuGrupo.Text = UtilFormatacao.ObtenhaPrimeiraLetraDoNome(nomeGrupo);
}
}
private void ObtemImagemArredondadaContato(int codigo)
{
using (var bmp = UtilImagem.ObtemImagemArredondado(UtilImagem.ObtemImagemLocalContato(codigo), 60, 80, 80))
{
_DicAvatarContato.Add(codigo, bmp);
}
}
private void ObtemImagemArredondadaGrupo(int codigoGrupo)
{
using (var bmp = UtilImagem.ObtemImagemArredondado(UtilImagem.ObtemImagemLocalGrupo(codigoGrupo), 60, 80, 80))
{
_DicAvatarGrupo.Add(codigoGrupo, bmp);
}
}
public bool EhGrupo(Object objeto)
{
return object.Equals(objeto.GetType(),
typeof(Grupo));
}
private int ObtenhaCodigoGrupoOuUsuario(int position)
{
if (EhGrupo(_ListaCompleta[position]))
{
Grupo G = (Grupo)_ListaCompleta[position];
return G.CodigoDoGrupo;
}
else
{
Usuario U = (Usuario)_ListaCompleta[position];
return U.Codigo;
}
}
public void AdicionaNovoContato(Usuario usario)
{
}
public void RemoveContato(Usuario usuario)
{
}
public void AdicionaNovoGrupo(Grupo grupo)
{
}
public void RemoveGrupo(Grupo grupo)
{
}
public override int GetItemViewType(int position)
{
return base.GetItemViewType(position);
}
public int GetCount()
{
return _ListaCompleta.Count;
}
public override Java.Lang.Object GetItem(int position)
{
return ObtenhaCodigoGrupoOuUsuario(position);
}
public Object ObtenhaTipoObjeto(int position)
{
return _ListaCompleta[position];
}
public Grupo ObtenhaGrupoDaLista(int codigo)
{
foreach (var item in _Listagrupos)
{
if (item.CodigoDoGrupo == codigo)
return item;
}
return null;
}
public override long GetItemId(int position)
{
return ObtenhaCodigoGrupoOuUsuario(position);
}
public override int Count
{
get { return _ListaCompleta.Count; }
}
private class ViewHolderContato : Java.Lang.Object
{
public TextView txtNome { get; set; }
public TextView txtCargo { get; set; }
public TextView txtPrimeiraLetraNomeOuGrupo { get; set; }
public ImageView imgAvatar { get; set; }
}
}
Simply call notifyDataSetChanged on your Adapter. This will inform it that the data inside the ListView has changed.
More info here: http://developer.android.com/reference/android/widget/BaseAdapter.html#notifyDataSetChanged()
Related
I have a model class:
public class Home_Model_ViewPager {
public String buttonLink;
public String tipsDescription;
public String tipsButton;
public Context context;
public Home_Model_ViewPager( Context context, String tipsDescription, String tipsButton, String buttonLink) {
this.context = context;
this.tipsDescription = tipsDescription;
this.tipsButton = tipsButton;
this.buttonLink = buttonLink;
}
public String getButtonLink() {
return buttonLink;
}
public void setButtonLink(String buttonLink) {
this.buttonLink = buttonLink;
}
public String getTipsDescription() {
return tipsDescription;
}
public void setTipsDescription(String tipsDescription) {
this.tipsDescription = tipsDescription;
}
public String getTipsButton() {
return tipsButton;
}
public void setTipsButton(String tipsButton) {
this.tipsButton = tipsButton;
}
}
I have used this model class to use it in viewpager adapter.
So, I am using a recyclerview and setting data to it. Now I have a problem that I have a viewpager in recycleritem. I want to return the size of viewpager adapter of any element in Home_Model_ViewPager as each element has diff size.
This is what I tried in ViewPagerAdapter:
public class ViewPagerAdapter extends PagerAdapter {
// Declare Variables
Context context;
LayoutInflater inflater;
List<Home_Model_ViewPager> totalList;
public ViewPagerAdapter(Context context, List<Home_Model_ViewPager> totalList) {
this.context = context;
this.totalList = totalList;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return totalList.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, final int position) {
// Declare Variables
TextView tricksDescription;
Button tricksButton;
View itemView = inflater.inflate(R.layout.viewpager_item, container,
false);
tricksDescription = itemView.findViewById(R.id.xtv_tricks_description);
tricksButton = itemView.findViewById(R.id.tricks_button);
tricksDescription.setText(Html.fromHtml(totalList.get(position).getTipsDescription()));
tricksButton.setText(Html.fromHtml(totalList.get(position).getTipsButton()));
tricksButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
String url = totalList.get(position).getButtonLink();
intent.setData(Uri.parse(url));
startActivity(intent);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
container.addView(itemView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
I am using volley to get the values as JSON..
private void Home() {
try {
if (getActivity()!=null)
Commonfunctions.LoadPreferences(getActivity());
System.out.println("Authtoken:" + Commonfunctions.Token_key);
appservice.View_All_Events(Commonfunctions.Token_key, String.valueOf(pagenumber), new Server_Callback() {
#Override
public void onSuccess(String response) {
System.out.println("HOME Response :" + response);
try {
JSONObject signObject = new JSONObject(response);
String resStatus = signObject.getString(AppConstants.STATUS);
String resCode = signObject.getString(AppConstants.CODE);
String resMsg = signObject.getString(AppConstants.MSG);
if (resCode.equals(AppConstants.SUCCESS_CODE)) {
JSONArray allEvents = signObject.getJSONArray("all");
System.out.println("INNER Response :" + allEvents);
for (int i = 0; i < allEvents.length(); i++) {
JSONObject innerObj1 = allEvents.getJSONObject(i);
String backgroundImg = innerObj1.getString("backg_img");
String declinedCount = innerObj1.getString("decli_count");
String acceptedCount = innerObj1.getString("accep_count");
String invitedCount = innerObj1.getString("invi_count");
String messages = innerObj1.getString("i_chat");
String name = innerObj1.getString("name");
String eventTime = innerObj1.getString("duration");
String userPhoto = innerObj1.getString("photo");
JSONArray viewpagerEvents = innerObj1.getJSONArray("action");
for (int u = 0; u < viewpagerEvents.length(); u++) {
JSONObject innerObj3 = viewpagerEvents.getJSONObject(u);
String buttonText = innerObj3.getString("text");
String tipsDesc = innerObj3.getString("action_text");
String buttonLink = innerObj3.getString("button_link");
final Home_Model home_data = new Home_Model(name, messages,invitedCount,declinedCount,acceptedCount,eventTime,
userPhoto,backgroundImg);
data.add(home_data);
final Home_Model_ViewPager home_viewpager = new Home_Model_ViewPager(getContext(),tipsDesc,buttonText, buttonLink);
viewPagerData.add(home_viewpager);
}
}
adapter = new HomeAdapter(getContext(),data);
pagerAdapter = new ViewPagerAdapter(getActivity(), viewPagerData);
home_recycler.setAdapter(adapter);
adapter.notifyDataSetChanged();
if (adapter.getItemCount()==0) {
noeventLayout.setVisibility(View.VISIBLE);
}
else {
noeventLayout.setVisibility(View.GONE);
}
} else if (resCode.equals(AppConstants.UPDATE_CODE)) {
//Version_Update versionUpdate=new Version_Update(SignIn.this,response);
} else {
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Commonfunctions.showerrorsnackbar(resMsg, getActivity(), parentLayout);
}
} catch (JSONException e) {
e.printStackTrace();
}
}//on success close
});//server callback closed
} catch (Exception e) {
e.printStackTrace();
}
}
HomeAdapter:
class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ViewHolder> {
Context context;
List<Home_Model> students;
public HomeAdapter(Context context,List<Home_Model> students) {
this.context = context;
this.students = students;
}
#Override
public HomeAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.event_home_list, viewGroup, false);
return new HomeAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(final HomeAdapter.ViewHolder holder, final int position) {
holder.title.setText(students.get(position).getName());
holder.invited.setText(students.get(position).getInvited());
holder.accepted.setText(students.get(position).getAccept());
holder.declined.setText(students.get(position).getDecline());
holder.eventTime.setText(students.get(position).getEvent_time());
holder.messages.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(),Chat_view.class));
}
});
holder.viewPager.setAdapter(pagerAdapter);
holder.dots = new ImageView[holder.dotsCount];
for (int i = 0; i < holder.dotsCount; i++) {
holder.dots[i] = new ImageView(context);
holder.dots[i].setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_dot_gray ));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.setMargins(8, 0, 8, 0);
holder.sliderDots.addView(holder.dots[i], params);
}
holder.dots[0].setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_dot_colorprimary));
holder.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
for (int i = 0; i < holder.dotsCount; i++) {
holder.dots[i].setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_dot_gray));
}
holder.dots[position].setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_dot_colorprimary));
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
if (students.get(position).getMessages().contentEquals("false")) {
holder.status.setVisibility(View.INVISIBLE);
}
else {
holder.status.setVisibility(View.VISIBLE);
}
holder.status.setVisibility(View.INVISIBLE);
try {
Glide.with(getActivity()).load(students.get(position).getProimg()).into(holder.pro_img);
Glide.with(getActivity()).load(students.get(position).getBgimg()).into(holder.card_main);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public int getItemCount() {
return students.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView title, messages, invited, accepted, declined, eventTime;
private PorterShapeImageView pro_img;
ImageView card_main, status;
ViewPager viewPager;
LinearLayout sliderDots;
private ImageView[] dots;
private int dotsCount;
public ViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.xtv_welcome);
messages = itemView.findViewById(R.id.xtv_message);
invited = itemView.findViewById(R.id.xtv_invited);
accepted = itemView.findViewById(R.id.xtv_accepted);
declined = itemView.findViewById(R.id.xtv_decline);
eventTime = itemView.findViewById(R.id.contact_number);
pro_img = itemView.findViewById(R.id.pro_pic);
card_main = itemView.findViewById(R.id.card_main);
status = itemView.findViewById(R.id.incoming_image);
viewPager = itemView.findViewById(R.id.viewPagerTips);
sliderDots = itemView.findViewById(R.id.sliderDots);
dotsCount = pagerAdapter.getCount();
}
}
}
Please try to make one different array list for your viewpager's adapter:
ArrayList<Home_Model_ViewPager> tempList = new ArrayList<>();
for(int k=0;k<viewpagerData.size();k++){
Home_Model_ViewPager object = viewPagerData.get(k);
if(object.getTripDesc()!=null && object.getTripDesc().length() >0){
tempList.add(object);
}
}
ViewPagerAdapter pagerAdapter = new ViewPagerAdapter(getActivity(), tempList);
home_recycler.setAdapter(adapter);
adapter.notifyDataSetChanged();
I am currently working on an app, that finds all MP3s on a users phone and then puts them into a list. This works very fine and is very quick, even with many songs. Now I populate a new list with an object for each item of the list to then display it inside my recyclerview. The problem is, that I have 700+ songs on my phone and this blocks the UI thread quite some time.
Now, I want to use the recyclerview to not load all items from the list into the objects all at once but rather only when they are about to be displayed - but I have NO clue over how to do this. Right now, all objects are build and then displayed in a very long scrollview from the recyclerview after the UI thread has been blocked for a good 30 seconds. Can please anyone help me? Here is my code:
namespace Media_Player
{
[Activity(Label = "Media_Player", MainLauncher = true)]
public class MainActivity : Activity
{
static public MediaPlayer mediaPlayer;
List<MP3object> mp3;
MediaMetadataRetriever reader;
public static Button btn_StartOrPause, btn_Stop;
public static TextView txt_CurrentSong;
public static bool stopIsActive = false, firstStart = true;
public static Android.Net.Uri CurrentActiveSongUri;
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
PhotoAlbumAdapter mAdapter;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.test);
reader = new MediaMetadataRetriever();
PopulateMP3List(ReturnPlayableMp3(true));
mediaPlayer = new MediaPlayer();
InitRecView();
}
private void InitRecView()
{
// Instantiate the adapter and pass in its data source:
mAdapter = new PhotoAlbumAdapter(mp3);
// Get our RecyclerView layout:
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);
// Plug the adapter into the RecyclerView:
mRecyclerView.SetAdapter(mAdapter);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.SetLayoutManager(mLayoutManager);
}
private void PopulateMP3List(List<string> content)
{
mp3 = new List<MP3object>();
foreach (string obj in content)
{
WriteMetaDataToFileList(obj);
}
}
void WriteMetaDataToFileList(string obj)
{
reader.SetDataSource(obj);
//Write Mp3 as object to global list
MP3object ob = new MP3object();
{
if(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != null)
{
ob.SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
}
else
{
ob.SongName = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != null)
{
ob.ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
}
else
{
ob.ArtistName = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != null)
{
ob.AlbumName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum);
}
else
{
ob.AlbumName = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
{
ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
}
else
{
ob.Year = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
{
ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
}
else
{
ob.Year = Resources.GetString(Resource.String.Unknown);
}
ob.Mp3Uri = obj; // can never be unknown!
ob.DurationInSec = int.Parse(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyDuration)) / 1000; // can never be unknown, div by 1000 to get sec not millis
}
mp3.Add(ob);
}
public List<string> ReturnPlayableMp3(bool sdCard)
{
List<string> res = new List<string>();
string phyle;
string path1 = null;
if(sdCard) // get mp3 from SD card
{
string baseFolderPath = "";
try
{
bool getSDPath = true;
Context context = Application.Context;
Java.IO.File[] dirs = context.GetExternalFilesDirs(null);
foreach (Java.IO.File folder in dirs)
{
bool IsRemovable = Android.OS.Environment.InvokeIsExternalStorageRemovable(folder);
bool IsEmulated = Android.OS.Environment.InvokeIsExternalStorageEmulated(folder);
if (getSDPath ? IsRemovable && !IsEmulated : !IsRemovable && IsEmulated)
baseFolderPath = folder.Path;
}
}
catch (Exception ex)
{
Console.WriteLine("GetBaseFolderPath caused the following exception: {0}", ex);
}
string xy = baseFolderPath.Remove(18); // This is result after this, but this hard coded solution could be a problem on different phones.: "/storage/05B6-2226/Android/data/Media_Player.Media_Player/files"
path1 = xy;
// path to SD card and MUSIC "/storage/05B6-2226/"
}
else // get Mp3 from internal storage
{
path1 = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);
foreach (string currentFile in mp3Files)
{
phyle = currentFile;
res.Add(phyle);
}
return res;
}
}
public class PhotoViewHolder : RecyclerView.ViewHolder
{
public ImageView Image { get; private set; }
public TextView Caption { get; private set; }
public PhotoViewHolder(View itemView) : base(itemView)
{
// Locate and cache view references:
Image = itemView.FindViewById<ImageView>(Resource.Id.imageView);
Caption = itemView.FindViewById<TextView>(Resource.Id.textView);
}
}
public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public List<MP3object> mp3;
public PhotoAlbumAdapter(List<MP3object> mp3)
{
this.mp3 = mp3;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.lay, parent, false);
PhotoViewHolder vh = new PhotoViewHolder(itemView);
return vh;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;
vh.Caption.Text = mp3[position].SongName;
}
public override int ItemCount
{
get { return mp3.Count(); }
}
}
}
So getting the list of strings with the locations of the Mp3 works very quickly, but then "WriteMetaDataToFileList(obj)" kicks in, comming from "PopulateMP3List(List content)" and this is what takes so long. What I think I need is for the recyclerview to only build the first 20 objects, and when the user starts scrolling, builds the next 20 objects and attaches them to list for them to also be scrolled. Please help me out here :)
Here is an abstract class:
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
private LinearLayoutManager linearLayoutManager;
protected PaginationScrollListener(LinearLayoutManager linearLayoutManager) {
this.linearLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = linearLayoutManager.getChildCount();
int totalItemCount = linearLayoutManager.getItemCount();
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
loadMoreItems();
}
}
}
protected abstract void loadMoreItems();
public abstract boolean isLastPage();
public abstract boolean isLoading();
}
and In your adapter you must follow this pattern:
public class ConsultancyAdapter extends RecyclerView.Adapter<ConsultancyAdapter.ConsultancyVH> {
private static final int ITEM = 0;
private static final int LOADING = 1;
private boolean isLoadingAdded = false;
public ConsultancyAdapter(List<Consultancy> consultancies, ConsultancyAdapterListener listener) {
}
#NonNull
#Override
public ConsultancyVH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ITEM:
viewHolder = getViewHolder(parent, layoutInflater);
break;
case LOADING:
View v2 = layoutInflater.inflate(R.layout.item_progress, parent, false);
viewHolder = new ConsultancyVH(v2);
break;
}
return (ConsultancyVH) viewHolder;
}
#NonNull
private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
RecyclerView.ViewHolder viewHolder;
View v1 = inflater.inflate(R.layout.item_consultancy, parent, false);
viewHolder = new ConsultancyVH(v1);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ConsultancyVH holder, int position) {
Consultancy consultancy = consultancies.get(position);
switch (getItemViewType(position)) {
case ITEM:
ConsultancyVH mySingeCounseller = holder;
holder.title.setText(consultancy.getTitle()); // set cardTitle
holder.fieldArea.setText(consultancy.getField_filedoctorskills());
break;
case LOADING:
break;
}
}
#Override
public int getItemCount() {
return consultancies.size();
}
#Override
public int getItemViewType(int position) {
return (position == consultancies.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
}
public void add(Consultancy mc) {
consultancies.add(mc);
notifyItemInserted(consultancies.size() - 1);
}
public void addAll(List<Consultancy> mcList) {
for (Consultancy mc : mcList) {
add(mc);
}
}
public void remove(Consultancy city) {
int position = consultancies.indexOf(city);
if (position > -1) {
consultancies.remove(position);
notifyItemRemoved(position);
}
}
public Consultancy getItem(int position) {
return consultancies.get(position);
}
public void clear() {
isLoadingAdded = false;
while (getItemCount() > 0) {
remove(getItem(0));
}
}
public boolean isEmpty() {
return getItemCount() == 0;
}
public void addLoadingFooter() {
isLoadingAdded = true;
add(new Consultancy());
}
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = consultancies.size() - 1;
Consultancy item = getItem(position);
if (item != null) {
consultancies.remove(position);
notifyItemRemoved(position);
}
}
public interface ConsultancyAdapterListener {
void onCaseClicked(int position, String nid, String fieldArea, String title);
}
protected class ConsultancyVH extends RecyclerView.ViewHolder {
private TextView title, fieldArea;
private CircleImageView iconProfile;
private MaterialRippleLayout caseButtonRipple;
public ConsultancyVH(View itemView) {
super(itemView);
caseButtonRipple = itemView.findViewById(R.id.case_button_ripple);
this.title = itemView.findViewById(R.id.docName);
this.fieldArea = itemView.findViewById(R.id.fieldArea);
this.iconProfile = itemView.findViewById(R.id.icon_profile);
}
}
}
and in your activity:
private void setScrollListener() {
recyclerView.addOnScrollListener(new PaginationScrollListener(linearLayoutManager) {
#Override
protected void loadMoreItems() {
isLoading = true;
currentPage += 1;
loadNextPage();
}
#Override
public boolean isLastPage() {
return isLastPage;
}
#Override
public boolean isLoading() {
return isLoading;
}
});
loadFirstPage();
}
and in my loadFirstPage i talk to a API and you need some your code:
private void loadFirstPage() {
CallData().enqueue(new DefaultRetrofitCallback<List<Consultancy>>() {
#Override
protected void onFailure(Throwable t) {
super.onFailure(t);
}
#Override
protected void onSuccess(List<Consultancy> response) {
swipeRefreshLayout.setRefreshing(false);
dataList = response;
adapter.addAll(dataList);
recyclerView.setAdapter(adapter);
if (!checkLast(response)) adapter.addLoadingFooter();
else isLastPage = true;
}
#Override
protected void onOtherStatus(Response<List<Consultancy>> response) {
super.onOtherStatus(response);
}
#Override
protected void always() {
super.always();
}
});
}
and loadNextPage:
private void loadNextPage() {
CallData().enqueue(new DefaultRetrofitCallback<List<Consultancy>>() {
#Override
protected void onFailure(Throwable t) {
super.onFailure(t);
}
#Override
protected void onSuccess(List<Consultancy> response) {
swipeRefreshLayout.setRefreshing(false);
adapter.removeLoadingFooter();
isLoading = false;
swipeRefreshLayout.setRefreshing(false);
adapter.addAll(response);
if (!checkLast(response)) adapter.addLoadingFooter();
else isLastPage = true;
}
#Override
protected void onOtherStatus(Response<List<Consultancy>> response) {
super.onOtherStatus(response);
}
#Override
protected void always() {
super.always();
}
});
}
I have a recyclerview that display news.
News is composed by name_news,image_news,time_news.
I am getting the data from mysqldatabse.
This is my adapter class:
public class PostAdapter2 extends RecyclerView.Adapter<PostAdapter2.ViewHolder>{
public Context c;
public FragmentManager mContext;
public ArrayList<News_data> original_items = new ArrayList<>();
public ArrayList<News_data> filtered_items = new ArrayList<>();
public ArrayList<Simplenews_data> original_items2 = new ArrayList<>();
public ArrayList<Simplenews_data> filtered_items2 = new ArrayList<>();
// ItemFilter mFilters = new ItemFilter();
public PostAdapter2(Context c, ArrayList<News_data> postList) {
this.c = c;
this.original_items = postList;
this.filtered_items = postList;
}
public PostAdapter2(FragmentManager mContext, ArrayList<Simplenews_data> postList) {
this.mContext = mContext;
this.original_items2 = postList;
this.filtered_items2 = postList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_news, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
try {
final Simplenews_data post = filtered_items2.get(position);
PicassoClient.downloadImage(c, post.getImage_simplenews(), holder.image_news);
holder.txt_news_title.setText(post.getName_simplenews());
holder.txt_date.setText(post.getTime_simplenews());
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onItemClick() {
Bundle x = new Bundle();
x.putString("news_title", post.getName_simplenews());
x.putString("news", post.getDesc_simplenews());
x.putString("image",post.getImage_simplenews());
x.putString("time",post.getTime_simplenews());
x.putString("date",post.getDate_simplenews());
Fragment descriptionFragment = new DescriptionFragment();
FragmentTransaction transaction = mContext.beginTransaction();
descriptionFragment.setArguments(x);
transaction.replace(R.id.framelayout, descriptionFragment).addToBackStack(null).commit();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public int getItemCount() {
return filtered_items2.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ItemClickListener itemClickListener;
TextView txt_news_title,txt_date;
ImageView image_news;
public ViewHolder(View itemView) {
super(itemView);
txt_news_title = (TextView) itemView.findViewById(R.id.txt_news_title);
txt_date = (TextView) itemView.findViewById(R.id.txt_timedate);
image_news = (ImageView) itemView.findViewById(R.id.image_news);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
try {
this.itemClickListener.onItemClick();
}catch (Exception e)
{
e.printStackTrace();
}
}
public void setItemClickListener(ItemClickListener itemClickListener)
{
this.itemClickListener=itemClickListener;
}
}
}
I am using a PHP interface to add news.
The getTime_simplenews() contains the news sumbmitted time format as : 14:00
So i want to display the immediate news in Top of recyclerview not under the previous news.
Thanks a lot.
UPDATED :
public class Simplenews_data {
int id_simplenews;
String name_simplenews,image_simplenews,desc_simplenews,time_simplenews,date_simplenews;
public String getDate_simplenews() {
return date_simplenews;
}
public void setDate_simplenews(String date_simplenews) {
this.date_simplenews = date_simplenews;
}
public String getTime_simplenews() {
return time_simplenews;
}
public void setTime_simplenews(String time_simplenews) {
this.time_simplenews = time_simplenews;
}
public int getId_simplenews() {
return id_simplenews;
}
public void setId_simplenews(int id_simplenews) {
this.id_simplenews = id_simplenews;
}
public String getName_simplenews() {
return name_simplenews;
}
public void setName_simplenews(String name_simplenews) {
this.name_simplenews = name_simplenews;
}
public String getImage_simplenews() {
return image_simplenews;
}
public void setImage_simplenews(String image_simplenews) {
this.image_simplenews = image_simplenews;
}
public String getDesc_simplenews() {
return desc_simplenews;
}
public void setDesc_simplenews(String desc_simplenews) {
this.desc_simplenews = desc_simplenews;
}
Fragment Code:
public void parseJson2(String response) {
try {
JSONArray array = new JSONArray(response);
JSONObject jsonObject = null;
post_array2.clear();
Simplenews_data p;
for (int i = 0; i < array.length(); i++) {
jsonObject = array.getJSONObject(i);
int id_simplenews = jsonObject.getInt("id_simplenews");
String name_simplenews = jsonObject.getString("name_simplenews");
String image_simplenews = jsonObject.getString("image_simplenews");
String desc_simplenews = jsonObject.getString("desc_simplenews");
String time_simplenews = jsonObject.getString("time_simplenews");
String date_simplenews = jsonObject.getString("date_simplenews");
p = new Simplenews_data();
p.setId_simplenews(id_simplenews);
p.setName_simplenews(name_simplenews);
p.setImage_simplenews(image_simplenews);
p.setDesc_simplenews(desc_simplenews);
p.setTime_simplenews(time_simplenews);
p.setDate_simplenews(date_simplenews);
post_array2.add(p);
}
} catch (JSONException e) {
swipeRefreshLayout.setRefreshing(false);
e.printStackTrace();
}
adapter = new PostAdapter2(getFragmentManager(), post_array2);
recycler_post.setAdapter(adapter);
swipeRefreshLayout.setRefreshing(false);
}
I have updated your model class and implemented Comparable to it
public class Simplenews_data implements Comparable<Simplenews_data> {
int id_simplenews;
String name_simplenews,image_simplenews,desc_simplenews,time_simplenews,date_simplenews;
public String getDate_simplenews() {
return date_simplenews;
}
public void setDate_simplenews(String date_simplenews) {
this.date_simplenews = date_simplenews;
}
public String getTime_simplenews() {
return time_simplenews;
}
public void setTime_simplenews(String time_simplenews) {
this.time_simplenews = time_simplenews;
}
public int getId_simplenews() {
return id_simplenews;
}
public void setId_simplenews(int id_simplenews) {
this.id_simplenews = id_simplenews;
}
public String getName_simplenews() {
return name_simplenews;
}
public void setName_simplenews(String name_simplenews) {
this.name_simplenews = name_simplenews;
}
public String getImage_simplenews() {
return image_simplenews;
}
public void setImage_simplenews(String image_simplenews) {
this.image_simplenews = image_simplenews;
}
public String getDesc_simplenews() {
return desc_simplenews;
}
public void setDesc_simplenews(String desc_simplenews) {
this.desc_simplenews = desc_simplenews;
}
#Override
public int compareTo(MyObject o) {
Date newDate = formatDateTime(o.getTime_simplenews(), "HH:mm", "YYYY-MM-DD HH:mm");
Date inputDate = formatDateTime(getTime_simplenews(), "HH:mm", "YYYY-MM-DD HH:mm");
return inputDate.compareTo(newDate);
}
public Date formatDateTime(String date, String fromFormat, String toFormat) {
Date d = null;
try {
d = new SimpleDateFormat(fromFormat, Locale.US).parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return new SimpleDateFormat(toFormat, Locale.US).parse(d);
}
}
Sort the list using below code
Collections.sort(yourList);
https://github.com/bignerdranch/expandable-recycler-view
With the help of the above library, I was able to implement a expandable RecyclerView, the expand and collapse all works fine. Now I need the different click listeners for child and parent. I was able to able implement a click listener, but I'm having trouble finding the child and parent positions.
the position integer variable available inside the Adapter returns only the overall position in the case of a normal RecyclerView. When clicking parent and child items, it returns different values depending on whether the parent is expanded or collapsed.
What I really want is When I click a parent I want the parent position. And when I click a child I want the parent and child position.
This is my Adapter class
public class LeftNavAdapter : ExpandableRecyclerAdapter<LeftNavParentViewHolder, LeftNavChildViewHolder>
{
LayoutInflater _inflater;
public event EventHandler<int> ItemClick;
public LeftNavAdapter(Context context, List<IParentObject> itemList) : base(context, itemList)
{
_inflater = LayoutInflater.From(context);
}
#region implemented abstract members of ExpandableRecyclerAdapter
public override LeftNavParentViewHolder OnCreateParentViewHolder(ViewGroup parentViewGroup)
{
var view = _inflater.Inflate(Resource.Layout.left_nav_item_parent, parentViewGroup, false);
return new LeftNavParentViewHolder(view);
}
public override LeftNavChildViewHolder OnCreateChildViewHolder(ViewGroup childViewGroup)
{
var view = _inflater.Inflate(Resource.Layout.left_nav_item_child, childViewGroup, false);
return new LeftNavChildViewHolder(view, OnChildClick);
}
public override void OnBindParentViewHolder(LeftNavParentViewHolder parentViewHolder, int position, object parentObject)
{
var parent = (LeftNavParent)parentObject;
parentViewHolder.nameTextView.Text = parent.title;
parentViewHolder.imageImageView.SetImageResource(parent.image);
if (parent.ChildObjectList.Count == 0)
parentViewHolder.exapandCollapseButton.Visibility = ViewStates.Gone;
}
public override void OnBindChildViewHolder(LeftNavChildViewHolder childViewHolder, int position, object childObject)
{
var child = (LeftNavChild) childObject;
childViewHolder.cNameTextView.Text = child.childTitle;
//childViewHolder._crimeSolvedCheckBox.CheckedChange += (object sender, CompoundButton.CheckedChangeEventArgs e) =>
//{
// Console.WriteLine("Child CheckedChanged Position: {0}", position);
//};
}
#endregion
private void OnChildClick(int position)
{
Console.WriteLine("checkpoint 2");
if (ItemClick != null)
{
Console.WriteLine("checkpoint 3");
ItemClick(this, position);
Console.WriteLine("checkpoint 4");
}
}
public override void OnParentItemClickListener(int position)
{
Toast.MakeText(_context, position + "touched", ToastLength.Short).Show();
if (_itemList[position] is IParentObject)
{
var parentObject = (IParentObject)_itemList[position];
if (parentObject.ChildObjectList.Count != 0)
{
ExpandParent(parentObject, position);
}
}
}
}
Expandable RecylerView class
public abstract class ExpandableRecyclerAdapter<PVH, CVH> : RecyclerView.Adapter, IParentItemClickListener
where PVH : ParentViewHolder
where CVH : ChildViewHolder
{
const int TypeParent = 0;
const int TypeChild = 1;
const string StableIdMap = "ExpandableRecyclerAdapter.StableIdMap";
const string StableIdList = "ExpandableRecyclerAdapter.StableIdList";
public const int CustomAnimationViewNotSet = -1;
public const long DefaultRotateDurationMs = 200;
public const long CustomAnimationDurationNotSet = -1;
Dictionary<long, bool> _stableIdMap;
ExpandableRecyclerAdapterHelper _adapterHelper;
IExpandCollapseListener _expandCollapseListener;
bool _parentAndIconClickable = false;
int _customParentAnimationViewId = CustomAnimationViewNotSet;
long _animationDuration = CustomAnimationDurationNotSet;
protected Context _context;
protected List<Object> _itemList;
protected List<IParentObject> _parentItemList;
#region Constructors
public ExpandableRecyclerAdapter(Context context, List<IParentObject> parentItemList)
: this(context, parentItemList, CustomAnimationViewNotSet, DefaultRotateDurationMs)
{
}
public ExpandableRecyclerAdapter(Context context, List<IParentObject> parentItemList,
int customParentAnimationViewId)
: this(context, parentItemList, customParentAnimationViewId, DefaultRotateDurationMs)
{
}
public ExpandableRecyclerAdapter(Context context, List<IParentObject> parentItemList,
int customParentAnimationViewId, long animationDuration)
{
_context = context;
_parentItemList = parentItemList;
_itemList = GenerateObjectList(parentItemList);
_adapterHelper = new ExpandableRecyclerAdapterHelper(_itemList);
_stableIdMap = GenerateStableIdMapFromList(_adapterHelper.HelperItemList);
_customParentAnimationViewId = customParentAnimationViewId;
_animationDuration = animationDuration;
}
#endregion
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup viewGroup, int viewType)
{
if (viewType == TypeParent)
{
var pvh = OnCreateParentViewHolder(viewGroup);
pvh.ParentItemClickListener = this;
return pvh;
}
else if (viewType == TypeChild)
{
return OnCreateChildViewHolder(viewGroup);
}
else
{
throw new ArgumentException("Invalid ViewType found");
}
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
if (_adapterHelper.GetHelperItemAtPosition(position) is ParentWrapper)
{
var parentViewHolder = (PVH)holder;
if (_parentAndIconClickable)
{
if (_customParentAnimationViewId != CustomAnimationViewNotSet &&
_animationDuration != CustomAnimationDurationNotSet)
{
parentViewHolder.SetCustomClickableViewAndItem(_customParentAnimationViewId);
parentViewHolder.AnimationDuration = _animationDuration;
}
else if (_customParentAnimationViewId != CustomAnimationViewNotSet)
{
parentViewHolder.SetCustomClickableViewAndItem(_customParentAnimationViewId);
parentViewHolder.CancelAnimation();
}
else
{
parentViewHolder.SetMainItemClickToExpand();
}
}
else
{
if (_customParentAnimationViewId != CustomAnimationViewNotSet &&
_animationDuration != CustomAnimationDurationNotSet)
{
parentViewHolder.SetCustomClickableViewOnly(_customParentAnimationViewId);
parentViewHolder.AnimationDuration = _animationDuration;
}
else if (_customParentAnimationViewId != CustomAnimationViewNotSet)
{
parentViewHolder.SetCustomClickableViewOnly(_customParentAnimationViewId);
parentViewHolder.CancelAnimation();
}
else
{
parentViewHolder.SetMainItemClickToExpand();
}
}
parentViewHolder.Expanded = ((ParentWrapper)_adapterHelper.GetHelperItemAtPosition(position)).Expanded;
OnBindParentViewHolder(parentViewHolder, position, _itemList[position]);
}
else if (_itemList[position] == null)
{
throw new NullReferenceException("Incorrect ViewHolder found");
}
else
{
OnBindChildViewHolder((CVH)holder, position, _itemList[position]);
}
}
private Dictionary<long, bool> GenerateStableIdMapFromList(List<Object> itemList)
{
var parentObjectHashMap = new Dictionary<long, bool>();
for (int i = 0; i < itemList.Count; i++)
{
if (itemList[i] != null)
{
var parentWrapper = (ParentWrapper)_adapterHelper.GetHelperItemAtPosition(i);
parentObjectHashMap.Add(parentWrapper.StableId, parentWrapper.Expanded);
}
}
return parentObjectHashMap;
}
private List<Object> GenerateObjectList(List<IParentObject> parentObjectList)
{
var objectList = new List<Object>();
foreach (var parentObject in parentObjectList)
{
objectList.Add(parentObject);
}
return objectList;
}
public override int ItemCount
{
get
{
return _itemList.Count;
}
}
public override int GetItemViewType(int position)
{
if (_itemList[position] is IParentObject)
{
return TypeParent;
}
else if (_itemList[position] == null)
{
throw new NullReferenceException("Null object added");
}
else
{
return TypeChild;
}
}
public void SetParentClickableViewAnimationDefaultDuration()
{
_animationDuration = DefaultRotateDurationMs;
}
public long AnimationDuration
{
get { return _animationDuration; }
set { _animationDuration = value; }
}
public int CustomParentAnimationViewId
{
get { return _customParentAnimationViewId; }
set { _customParentAnimationViewId = value; }
}
public bool ParentAndIconExpandOnClick
{
get { return _parentAndIconClickable; }
set { _parentAndIconClickable = value; }
}
public void RemoveAnimation()
{
_customParentAnimationViewId = CustomAnimationViewNotSet;
_animationDuration = CustomAnimationDurationNotSet;
}
public void AddExpandCollapseListener(IExpandCollapseListener expandCollapseListener)
{
_expandCollapseListener = expandCollapseListener;
}
public void ExpandParent(IParentObject parentObject, int position)
{
var parentWrapper = (ParentWrapper)_adapterHelper.GetHelperItemAtPosition(position);
if (parentWrapper == null)
{
return;
}
if (parentWrapper.Expanded)
{
parentWrapper.Expanded = false;
if (_expandCollapseListener != null)
{
var expandedCountBeforePosition = GetExpandedItemCount(position);
_expandCollapseListener.OnRecyclerViewItemCollapsed(position - expandedCountBeforePosition);
}
// Was Java HashMap put, need to replace the value
_stableIdMap[parentWrapper.StableId] = false;
//_stableIdMap.Add(parentWrapper.StableId, false);
var childObjectList = ((IParentObject)parentWrapper.ParentObject).ChildObjectList;
if (childObjectList != null)
{
for (int i = childObjectList.Count - 1; i >= 0; i--)
{
var pos = position + i + 1;
_itemList.RemoveAt(pos);
_adapterHelper.HelperItemList.RemoveAt(pos);
NotifyItemRemoved(pos);
}
}
}
else
{
parentWrapper.Expanded = true;
if (_expandCollapseListener != null)
{
var expandedCountBeforePosition = GetExpandedItemCount(position);
_expandCollapseListener.OnRecyclerViewItemExpanded(position - expandedCountBeforePosition);
}
// Was Java HashMap put, need to replace the value
_stableIdMap[parentWrapper.StableId] = true;
//_stableIdMap.Add(parentWrapper.StableId, true);
var childObjectList = ((IParentObject)parentWrapper.ParentObject).ChildObjectList;
if (childObjectList != null)
{
for (int i = 0; i < childObjectList.Count; i++)
{
var pos = position + i + 1;
_itemList.Insert(pos, childObjectList[i]);
_adapterHelper.HelperItemList.Insert(pos, childObjectList[i]);
NotifyItemInserted(pos);
}
}
}
}
private int GetExpandedItemCount(int position)
{
if (position == 0)
return 0;
var expandedCount = 0;
for (int i = 0; i < position; i++)
{
var obj = _itemList[i];
if (!(obj is IParentObject))
expandedCount++;
}
return expandedCount;
}
public Bundle OnSaveInstanceState(Bundle savedInstanceStateBundle)
{
savedInstanceStateBundle.PutString(StableIdMap, JsonConvert.SerializeObject(_stableIdMap));
return savedInstanceStateBundle;
}
public void OnRestoreInstanceState(Bundle savedInstanceStateBundle)
{
if (savedInstanceStateBundle == null)
return;
if (!savedInstanceStateBundle.ContainsKey(StableIdMap))
return;
_stableIdMap = JsonConvert.DeserializeObject<Dictionary<long, bool>>(savedInstanceStateBundle.GetString(StableIdMap));
var i = 0;
while (i < _adapterHelper.HelperItemList.Count)
{
if (_adapterHelper.GetHelperItemAtPosition(i) is ParentWrapper)
{
var parentWrapper = (ParentWrapper)_adapterHelper.GetHelperItemAtPosition(i);
if (_stableIdMap.ContainsKey(parentWrapper.StableId))
{
parentWrapper.Expanded = _stableIdMap[parentWrapper.StableId];
if (parentWrapper.Expanded)
{
var childObjectList = ((IParentObject)parentWrapper.ParentObject).ChildObjectList;
if (childObjectList != null)
{
for (int j = 0; j < childObjectList.Count; j++)
{
i++;
_itemList.Insert(i, childObjectList[j]);
_adapterHelper.HelperItemList.Insert(i, childObjectList[j]);
}
}
}
}
else
{
parentWrapper.Expanded = false;
}
}
i++;
}
NotifyDataSetChanged();
}
public abstract PVH OnCreateParentViewHolder(ViewGroup parentViewGroup);
public abstract CVH OnCreateChildViewHolder(ViewGroup childViewGroup);
public abstract void OnBindParentViewHolder(PVH parentViewHolder, int position, Object parentObject);
public abstract void OnBindChildViewHolder(CVH childViewHolder, int position, Object childObject);
#region IParentItemClickListener implementation
public abstract void OnParentItemClickListener(int position);
// {
//// if (_itemList[position] is IParentObject)
//// {
//// var parentObject = (IParentObject)_itemList[position];
////if (parentObject.ChildObjectList.Count != 0)
////{
//// ExpandParent(parentObject, position);
////}
//// }
// }
#endregion
}
This is how I accomplished it.
Created ChildViewHolder like this, passed an item click listener via constructor.
public class LeftNavChildViewHolder : ChildViewHolder
{
public TextView cNameTextView;
public LeftNavChildViewHolder(View itemView, Action<int> listener) : base(itemView)
{
cNameTextView = itemView.FindViewById<TextView>(Resource.Id.leftNavTitleChild);
itemView.Click += (sender, e) => listener(Position);
}
}
then in adapter:
public class LeftNavAdapter : ExpandableRecyclerAdapter<LeftNavParentViewHolder, LeftNavChildViewHolder>
{
public override LeftNavChildViewHolder OnCreateChildViewHolder(ViewGroup childViewGroup)
{
var view = _inflater.Inflate(Resource.Layout.left_nav_item_child, childViewGroup, false);
return new LeftNavChildViewHolder(view, OnChildClick);
}
void OnChildClick(int position)
{
// Do whatever you want
}
}
In the code below I have a ListView with a Items list containing Name, Id and Quantity. When I click on a row this value should be updated according to informed parameter in UpdateItemSelectedInListView () method. But only line 9 is having the changed value, independent of the line that I select.
Activity:
public class MainActivity : Activity
{
ListView _ListView;
AdapterItem _Adapter;
List<Item> _ListaItem = new List<Item>();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
CriaListView();
}
private void CriaListView()
{
_ListView = FindViewById<ListView>(Resource.Id.listaItems);
_ListView.ItemClick += _ListView_ItemClick;
_ListView.Adapter = CriaAdapter();
}
private AdapterItem CriaAdapter()
{
for (int i = 0; i < 15; i++)
{
_ListaItem.Add(new Item("Test Name",i));
}
_Adapter = new AdapterItem(this, _ListaItem);
return _Adapter;
}
void _ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
_Adapter.UpdateItemSelectedInListView(e.Position, 5);
}
}
Adapter:
public class AdapterItem : BaseAdapter
{
List<Item> _ListaItem = new List<Item>();
Activity _Activity;
LayoutInflater _Inflate;
ViewHolderItem _HolderItem;
Boolean _HasUpdate;
int _IdToUpDate;
int _NewQntd;
int _Position;
public AdapterItem(Activity activity, List<Item> listaItem)
{
_Activity = activity;
_ListaItem = listaItem;
try
{
_Inflate = (LayoutInflater)_Activity.GetSystemService(Context.LayoutInflaterService);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
View _View;
public override View GetView(int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
_View = convertView;
try
{
if (_View != null)
_HolderItem = _View.Tag as ViewHolderItem;
else
{
_View = _Activity.LayoutInflater.Inflate(Resource.Layout.LayoutItem, null);
_HolderItem = CriaViewHolder();
}
PopulaViewHolder(position);
_View.Tag = _HolderItem;
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return _View;
}
private ViewHolderItem CriaViewHolder()
{
ViewHolderItem holderItem = new ViewHolderItem();
holderItem.txtNameItem = _View.FindViewById<TextView>(Resource.Id.nameItem);
holderItem.txtIdItem = _View.FindViewById<TextView>(Resource.Id.idItem);
holderItem.txtqntItem = _View.FindViewById<TextView>(Resource.Id.totalInStock);
return holderItem;
}
private void PopulaViewHolder(int position)
{
_HolderItem.txtNameItem.Text = _ListaItem[position].nome;
_HolderItem.txtIdItem.Text = _ListaItem[position].id.ToString();
if (_HasUpdate && (position == _Position))
UpdateAdapter();
}
public void UpdateAdapter()
{
_HolderItem.txtqntItem.Text = _NewQntd.ToString();
_HasUpdate = false;
}
public void UpdateItemSelectedInListView(int position, int newValue)
{
_NewQntd = newValue;
_HasUpdate = true;
_Position = position;
this.NotifyDataSetChanged();
}
public override Java.Lang.Object GetItem(int position)
{
return 0;
}
public override int Count
{
get {return _ListaItem.Count; }
}
public override long GetItemId(int position)
{
return _ListaItem[position].id;
}
public override int GetItemViewType(int position)
{
return base.GetItemViewType(position);
}
public override int ViewTypeCount
{
get
{
return base.ViewTypeCount;
}
}
private class ViewHolderItem : Java.Lang.Object
{
public TextView txtNameItem { get; set; }
public TextView txtIdItem { get; set; }
public TextView txtqntItem { get; set; }
}
}
You need to move _View.Tag = _HolderItem; inside of the else on the GetView method:
public override View GetView(int position, Android.Views.View convertView, Android.Views.ViewGroup parent)
{
_View = convertView;
try
{
if (_View != null)
_HolderItem = _View.Tag as ViewHolderItem;
else
{
_View = _Activity.LayoutInflater.Inflate(Resource.Layout.LayoutItem, null);
_HolderItem = CriaViewHolder();
//Set the tag only when you create a new one
//otherwise you'll have the problem you are having
_View.Tag = _HolderItem;
}
PopulaViewHolder(position);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return _View;
}
It seems that your _Adapter.UpdateItemSelectedInListView not fetching correct position as it looses the state. Instead you can make use of binding "event action" to each view row from viewholder class.
On trigger of this action event [ in GetView()] another event action to activity class to process Click event.
//Viewholder class
internal Action ActionImgViewSelectedToGetView{ get; set;}
internal void Initialize(View view)
{
imgItem=view.FindViewById<ImageView> (Resource.Id.imgItem);
imgItem.Click += delegate(object sender , EventArgs e )
{
ActionImgViewSelectedToGetView(); //action event to getview()
};
}
//in getview()
viewHolder.ActionImgViewSelectedToGetView = () =>
{
if(ActionImgSelectedToActivity!=null)
ActionImgSelectedToActivity(_lstItem[position].ItemName); //action event,targeting to activity class method
};
//activity
if ( objItemAdapter != null )
{
objItemAdapter.ActionImgSelectedToActivity -= SelectedItem;
objItemAdapter = null;
}
objItemAdapter = new ItemAdapterClass (this, lstItem);
objItemAdapter.ActionImgSelectedToActivity += SelectedItem;
listViewItem.Adapter = objItemAdapter;
void SelectedItem( string strItemName)
{
//seleced item
}
for more detail : http://appliedcodelog.blogspot.in/2015/07/working-on-issues-with-listview-in.html#WrongPosition