ListView item as a progress bar

TBMSamTBMSam Member ✭✭
edited November 19 in Xamarin.Android

Hello guys,

I was wondering if someone can maybe help me with the following intent:

I created an app which simply displays a table. It shows a table head and beyond that a list view which contains several items.
Is it possible, that if one clicks on one of these items, a progress bar is shown which loads smoothely in a certain time interval (lets say 30 seconds) from left to right?

Please see my screenshot below, maybe it's easier to understand what I am trying to do:

Finally, I don't know if it helps, but let me attach some code as well. I shortened it a little, if something is missing for understanding (like the list class) or if I removed to much, please let me know:

public class TableActivity : Activity
{
    ListView lv;
    ListAdapter adapter = null;
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        //...
        lv = FindViewById<ListView>(Resource.Id.geraeteListView);
        adapter = new ListAdapter(this, Resource.Layout.List, geraeteliste.CurrentGeraeteliste, Intent.GetStringExtra("ServerIP"))
        {
            parentActivity = this
        };
        lv.Adapter = adapter;
    }

    private async void OnItemClick(object sender, AdapterView.ItemClickEventArgs e)
    {
        if (geraeteliste.CurrentGeraeteliste[e.Position].bespielt == "J") return;
        //…
        await Task.Delay(0);
    } 
}

public class ListAdapter : ArrayAdapter
{
    //...
    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        View v = convertView;
        if (v == null)
        {
            LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
            v = inflater.Inflate(Resource.Layout.List, parent, false);
        }
        //...
        v.FindViewById<ImageView>(Resource.Id.typeImageView).SetImageResource(Resource.Drawable.Icon);
        v.FindViewById<TextView>(Resource.Id.numberTextView).Text = Geraetelist[position].geraeteplatz;
        v.FindViewById<TextView>(Resource.Id.descriptionTextView).Text = Geraetelist[position].geraeteinformation;
        ImageView iv = v.FindViewById<ImageView>(Resource.Id.bspImageView);
        iv.SetImageResource(Geraetelist[position].bespielt == "N" ? Resource.Drawable.greenPoint : Resource.Drawable.redPoint);
        //…
        return v;        
    }
}

Can anyone maybe give me a short hint or something? How can I implement such a progress bar for every item on click?^^ Would be really happy for every helping effort.

Thanks in advance for every answer,

Best regards

Answers

  • jezhjezh Member, Xamarin Team Xamurai
    edited November 20

    You can try to add a ProgressBar in your item layout: List:

     <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"/>
    

    And use an AsyncTask to update the progress data.

    The equivalent C# code:

    public class UpdaterAsyncTask : AsyncTask
    {
    protected override void OnPreExecute()
    {
    }
    
    protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
    {
    }
    
    protected override void OnPostExecute(Java.Lang.Object result)
    {
    }
    }
    

    For more details,you can check the Listview with ProgressBar .

    You can also check the following link,it should be helpful for you.

    https://stackoverflow.com/questions/19689127/how-to-update-progressbar-in-a-listview-item

  • TBMSamTBMSam Member ✭✭
    edited November 22

    Hello @jezh and thank you so much for your answer,

    As advised, I added a ProgressBar in my item layout List:

    <ProgressBar 
        android:id="@+id/progressBar1" 
        style="@android:style/Widget.ProgressBar.Horizontal" />
    

    Furthermore, I extended the Code of my ListAdapter a little (amongst others by the progress attribute):

    public class ListAdapter : ArrayAdapter
    {
        public int progress;
    
        public ListAdapter(Context Context, int ListId, List<Geraet> Geraete, string serverip, int Progress) : base(Context, ListId, Geraete)
        {
            this.Geraetelist = Geraete;
            this.ip = serverip;
            this.progress = Progress;
        }
    
        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            View v = convertView;
            if (v == null)
            {
                LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
                v = inflater.Inflate(Resource.Layout.List, parent, false);
            }
            //…
            var progressBar = v.FindViewById<ProgressBar>(Resource.Id.progressBar1);
            progressBar.Visibility = ViewStates.Visible;
            progressBar.SetProgress(progress, true);
    
            return v;        
        }
    }
    

    Finally my Activity:

    public class MyActivity : Activity
    {
        ListView lv;
        ListAdapter adapter = null;
    
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.MyActivityLayout);
    
            lv = FindViewById<ListView>(Resource.Id.geraeteListView);
            lv.Visibility = Android.Views.ViewStates.Visible;
    
            adapter = new ListAdapter(this, Resource.Layout.List, geraeteliste.CurrentGeraeteliste, Intent.GetStringExtra("ServerIP"), 90)
            {
                parentActivity = this
            };
            lv.Adapter = adapter;
            lv.ItemClick += OnItemClick;
        }
    
        private async void OnItemClick(object sender, AdapterView.ItemClickEventArgs e)
        {
            RunOnUiThread(() =>
            {
                adapter.progress = 25;
                adapter.NotifyDataSetChanged();
            });
    
            await Task.Delay(0);
        }
    }
    

    On Click, it now sets the progress bar of every item within the list from 90 to 75, unfortunately not only of the clicked one as expected.

    Furthermore you mentioned something about an AsyncTask to update the progress data. When extending AsyncTask, he makes me only override one method:

    class ProgressBarUpdateTaskAsync : AsyncTask
    {
        protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
        {
            throw new NotImplementedException();
        }
    }
    

    When downloading your shared GitHub-Project, installing Android Studio and importing the project into it, I can find the following method in the FileDownloadTask-File:

    @Override
    protected Void doInBackground(Void... params) {
        Log.d(TAG, "Starting download for " + mInfo.getFilename());
        mInfo.setDownloadState(DownloadState.DOWNLOADING);
        for (int i = 0; i <= mInfo.getFileSize(); ++i) {
            try {
                Thread.sleep(16);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            publishProgress(i);
        }
        mInfo.setDownloadState(DownloadState.COMPLETE);
        return null;
    }
    

    But here, there are the other methods to override as well: onProgressUpdate, onPostExecute and onPreExecute. You mentioned them in your post also. They are only concerned to some kind of DownloadState? Do I just shall add those methods without the @Override annotation? Or what do I have to do to update the progress data in the end?^^ So that the progress bar loads within a certain time interval (e.g. 30 seconds) from 100% (right) to 0% (left)?

    Sorry for those stupid beginner questions, I am unfortunately only student employee and therefore a bit lacking of knowledge. :(

    I am nevertheless really thankful for each answer. Thanks as well again for every helping effort,

    Best regards

  • jezhjezh Member, Xamarin Team Xamurai

    I will try my best effert to convert the code into xamarin code for you.

  • jezhjezh Member, Xamarin Team Xamurai
    edited November 26

    I have converted Java code to c# code. And it works properly. The link is here.

    The main code is

    class FileDownloadTask

      public class FileDownloadTask : AsyncTask<Java.Lang.Void, int, Java.Lang.Void>
    {
        private static string TAG = "FileDownloadTask";
        private  DownloadInfo  mInfo;
    
        public FileDownloadTask(DownloadInfo mInfo)
        {
            this.mInfo = mInfo;
        }
    
        protected override void OnProgressUpdate(params int[] values)
        {
            //base.OnProgressUpdate(values);
    
            mInfo.setProgress(values[0]);
    
            ProgressBar bar = mInfo.getProgressBar();
    
            if (bar != null) {
                bar.Progress = mInfo.getProgress();
                bar.Invalidate();
            } 
        }
    
        protected override Java.Lang.Void RunInBackground(params Java.Lang.Void[] @params)
        {
            Log.Info(TAG, "Starting download for " + mInfo.getFilename());
            mInfo.setDownloadState(DownloadInfo.DownloadState.DOWNLOADING);
            for (int i = 0; i <= mInfo.getFileSize(); ++i)
            {
                try
                {
                    Thread.Sleep(16);
                }
                catch (InterruptedException e)
                {
                    e.PrintStackTrace();
                }
    
                PublishProgress(i);
            }
            mInfo.setDownloadState(DownloadInfo.DownloadState.COMPLETE);
            return null;
        }
    
        protected override void OnPostExecute(Java.Lang.Object result)
        {
            mInfo.setDownloadState(DownloadInfo.DownloadState.COMPLETE);
        }
    
        protected override void OnPreExecute()
        {
            mInfo.setDownloadState(DownloadInfo.DownloadState.DOWNLOADING);
        }
    }
    

    class DownloadInfoArrayAdapter

      public class DownloadInfoArrayAdapter : ArrayAdapter<DownloadInfo>
      {
        private Context context;
        public DownloadInfoArrayAdapter(Context context, int textViewResourceId,
                                    List<DownloadInfo> objects) : base(context, textViewResourceId, objects)
         {
            this.context = context;
         }
         public override View GetView(int position, View convertView, ViewGroup parent)
         {
            //return base.GetView(position, convertView, parent);
    
            View row = convertView;
            DownloadInfo info = GetItem(position);
    
            ViewHolder holder = null;
            if (null == row)
            {
                LayoutInflater inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
                row = inflater.Inflate(Resource.Layout.file_download_row, parent, false);
    
                holder = new ViewHolder();
                holder.textView = (TextView)row.FindViewById(Resource.Id.downloadFileName);
                holder.progressBar = (ProgressBar)row.FindViewById(Resource.Id.downloadProgressBar);
                holder.button = (Button)row.FindViewById(Resource.Id.downloadButton);
                holder.info = info;
    
                row.Tag = holder;
            }
            else
            {
                holder =  row.Tag as ViewHolder;
    
                holder.info.setProgressBar(null);
                holder.info = info;
                holder.info.setProgressBar(holder.progressBar);
            }
    
            holder.textView.Text = info.getFilename();
    
            holder.progressBar.Progress = info.getProgress();
            holder.progressBar.Max = info.getFileSize();
    
            info.setProgressBar(holder.progressBar);
    
    
            holder.button.Enabled=  info.getDownloadState() == DownloadInfo.DownloadState.NOT_STARTED;
            Button button = holder.button;
    
            holder.button.Click += delegate {
                info.setDownloadState(DownloadInfo.DownloadState.QUEUED);
                button.Enabled = false;
                button.Invalidate();
                FileDownloadTask task = new FileDownloadTask(info);
                task.ExecuteOnExecutor(AsyncTask.ThreadPoolExecutor);
            };
    
            return row;
        }
    }
    

    Note
    1. In xamarin android, the equivalence code of @Override is override, when you input the override, optional override functions will appear.
    2. For this question On Click, it now sets the progress bar of every item within the list from 90 to 75, unfortunately not only of the clicked one as expected.

    we could use relative tag for the item to identify them. For example:

           ViewHolder holder = null;
            if (null == row)
            {
                LayoutInflater inflater = (LayoutInflater)context.GetSystemService(Context.LayoutInflaterService);
                row = inflater.Inflate(Resource.Layout.file_download_row, parent, false);
    
                holder = new ViewHolder();
                holder.textView = (TextView)row.FindViewById(Resource.Id.downloadFileName);
                holder.progressBar = (ProgressBar)row.FindViewById(Resource.Id.downloadProgressBar);
                holder.button = (Button)row.FindViewById(Resource.Id.downloadButton);
                holder.info = info;
    
                row.Tag = holder;  // add tag to item
            }
            else
            {
                holder =  row.Tag as ViewHolder;  // use the tag of item
    
                holder.info.setProgressBar(null);
                holder.info = info;
                holder.info.setProgressBar(holder.progressBar);
            }
    
  • jezhjezh Member, Xamarin Team Xamurai

    @TBMSam Have you resolved your question?

  • TBMSamTBMSam Member ✭✭

    Hello @jezh and thank you so much for your conversion and your helping effort.

    Unfortunately, I havn't managed to try it yet, as I have so much stress at my university right now :(

    Please excuse, I will try it in the course of the week and write as soon as I got it.

  • jezhjezh Member, Xamarin Team Xamurai

    @TBMSam If my reply is useful for you ,could you please mark it as an answer?

Sign In or Register to comment.