0

我尝试做一个视图来显示多个文件下载。ProgressDialog 非常适合显示单个文件下载信息,但我认为它不能用作 ListView 的元素或以某种方式设置多个文件指示(或者可以吗?)

所以我实现了自己的适配器,如一些指南中所示它工作正常,我可以添加下载项目(名称为 TextView + ProgressBar,最大设置为文件大小),但是如何在某些列表项中更新 ProgressBar?

如果这是一种不好的做法,哪种方式最好显示多个文件的下载进度?

下载项目.xml

<?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" >

<TextView
    android:id="@+id/download_label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<ProgressBar
    android:id="@+id/download_bar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@id/download_label" />
</RelativeLayout>

下载类

public class Download 
{
  public String name;
  public int size;

  public Download(String name, int size)
  {
    this.name = name;
    this.size = size;
  }
}

下载适配器类

 import android.content.Context;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ProgressBar;
 import android.widget.TextView;

 public class DownloadsAdapter extends ArrayAdapter<Download>
 {
   private int layoutResourceId;
   public DownloadsAdapter(Context context, int textViewResourceId)
   {
    super(context, textViewResourceId);
    this.layoutResourceId = textViewResourceId;
   }

   @Override
   public View getView(int position, View convertView, ViewGroup parent)
   {
     DownloadHolder downloadHolder = null;
         if(convertView == null)
         {
            LayoutInflater inflater = (LayoutInflater) super.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(layoutResourceId, parent, false);
            downloadHolder = new DownloadHolder();
            downloadHolder.progressBar = (ProgressBar)convertView.findViewById(R.id.download_bar);
            downloadHolder.label = (TextView)convertView.findViewById(R.id.download_label);
            Log.i("INFO", "HOLDER SET");
            convertView.setTag(downloadHolder);
         }
         else
         {
            downloadHolder = (DownloadHolder)convertView.getTag();
         }

        Download download = super.getItem(position);
        downloadHolder.label.setText(download.name);
        downloadHolder.progressBar.setIndeterminate(false);
        downloadHolder.progressBar.setMax(download.size);
        return convertView;
    }

public static class DownloadHolder
{
    ProgressBar progressBar;
    TextView label;
}

   }

下载查看类

import android.app.ListActivity;
import android.os.Bundle;

public class DownloadsView extends ListActivity
{
   public static DownloadsAdapter DOWNLOADS = null;

@Override
    protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      DOWNLOADS = new DownloadsAdapter(this, R.layout.download_item);
      setListAdapter(DOWNLOADS);
      //TEST
      /*
      DownloadsView.addDownload("Lol", 232);
      DownloadsView.addDownload("fsfs", 123);
     */ 
 }

    public static void addDownload(String name, int size)
    {   
      DOWNLOADS.add(new Download(name, size));
    }  
}
4

2 回答 2

2

好的,这就去...

package com.skype.transfer;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Vector;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.skype.api.Transfer;
import com.skype.ref.R;

/*****
 * This class is in charge of displaying ongoing transfers in a ListView
 * <p>
 * The methods of relevance are {@link #getItem()}, {@link #getCount()} and
 * {@link #getView()}.
 * 
 * @author Aleksandar Milenkovic
 */
public class TransferArrayAdapter extends ArrayAdapter<Transfer>
{
    private ArrayList<Transfer> values      = null;
    private Vector<Boolean>     selectedStates;
    private Context             context;

    private ImageView           transferType;
    private TextView            filename;
    private ProgressBar         progress;
    private TextView            details;

    private static final String ASSETS_DIR  = "images/";
    private static final String LOGTAG      = "TransferArrayAdapter";

    /**
     * The default constructor which is invoked to create the current transfers'
     * array adapter
     * 
     * @param context
     *            the application context
     * @param textViewResourceId
     *            The resource ID for a layout file containing a TextView to use
     *            when instantiating views.
     * @param objects
     *            the backing array populated by Buddy objects to be displayed.
     * @see {@link ArrayAdapter}<T>
     */
    public TransferArrayAdapter(Context context, int textViewResourceId, ArrayList<Transfer> objects)
    {
        super(context, textViewResourceId, objects);
        this.context = context;
        this.values = objects;
        //      selectedStates = new Vector<Boolean>();
        //      clearSelectedState();
    }

    /**
     * How many items are in the data set represented by this Adapter.
     * 
     * @return the trimmed size of the backing array.
     */
    @Override
    public int getCount()
    {
        this.values.trimToSize();
        return this.values.size();
    }

    /**
     * Get the data item associated with the specified position in the data set.
     * 
     * @param index
     *            Position of the item whose data we want within the adapter's
     *            data set.
     * @return the Transfer item at the indicated position in the backing array
     */
    @Override
    public Transfer getItem(int index)
    {
        if (index <= getCount())    //IndexOutOfBoundsException fix
            return this.values.get(index);
        return this.values.get(values.size());
    }

    /**
     * This method is used to generate views to be used in the ListView. This
     * the method that defines how data will look and be represented throughout
     * the UI.
     * 
     * @param position
     *            The position of the item that is being placed / The position
     *            of the item within the adapter's data set of the item whose
     *            view we want.
     *            <p>
     * @param convertView
     *            The old view to reuse, if possible. Note: You should check
     *            that this view is non-null and of an appropriate type before
     *            using. If it is not possible to convert this view to display
     *            the correct data, this method can create a new view.
     *            Heterogeneous lists can specify their number of view types, so
     *            that this View is always of the right type (see
     *            getViewTypeCount() and getItemViewType(int))
     *            <p>
     * @param parent
     *            The parent that this view will eventually be attached to
     * @return the view that defines how this Buddy object is represented in the
     *         ListView / A View corresponding to the data at the specified
     *         position.
     * 
     * @see {@link BaseAdapter#getView(int, View, ViewGroup)}
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View row = convertView;

        if (row == null)
        {
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.transfer_item, parent, false);
            //          row.setTag(convertView);
        }

        Transfer file = getItem(position);
        //      Log.d(LOGTAG, "getView(): file at position "+position+"= "+file);
        if (file == null) return row;

        transferType = (ImageView) row.findViewById(R.id.transfer_type);
        filename = (TextView) row.findViewById(R.id.transfer_filename);
        progress = (ProgressBar) row.findViewById(R.id.transfer_progress);
        details = (TextView) row.findViewById(R.id.transfer_details);

        //filename, progress, details
        filename.setText(FileUtils.getFilenameFor(file));
        progress.setProgress(FileUtils.getProgressFor(file));

        switch (FileUtils.getStatusFor(file))
        {
            case PAUSED:
                details.setText("Paused");
                break;

            case WAITING_FOR_ACCEPT:
                details.setText("Waiting...");
                break;

            case CANCELLED:
            case CANCELLED_BY_REMOTE:
                details.setText("Canceled");
                break;

            default:
                details.setText(FileUtils.getTransferInfo(file));
                break;
        }

        //image stuff
        String imgFilePath = ASSETS_DIR;
        switch (FileUtils.getTransferTypeFor(file))
        {
            case INCOMING:
                imgFilePath += "incoming_file.png";
                break;

            case OUTGOING:
                imgFilePath += "outcoming_file.png";
                break;
        }

        try
        {
            Bitmap bitmap = BitmapFactory.decodeStream(this.context.getResources().getAssets().open(imgFilePath));
            transferType.setImageBitmap(bitmap);
        } catch (IOException e)
        {
            Log.e(LOGTAG + "Exception", e.getMessage());
            e.printStackTrace();
            Log.e(LOGTAG, "Error while setting " + FileUtils.getFilenameFor(file) + " type icon to: " + imgFilePath);
        }

        return row;
    }

    /**
     * This method is used to clear all selection states on the view's children.
     */
    public void clearSelectedState()
    {
        selectedStates.clear();
        for (int i = 0; i <= getCount(); i++)
        {
            selectedStates.add(Boolean.valueOf(false));
        }
    }

    /**
     * This method is used to make a certain position 'selected'.
     * <p>
     * After setting selection, notifyDataSetChanged() will be called.
     * 
     * @param position
     *            the position to select
     */
    public void setSelectedState(int position)
    {
        //clear selected state vector
        clearSelectedState();
        //set selected position
        selectedStates.set(position, Boolean.valueOf(true));
        //refresh adapter to redraw focus
        notifyDataSetChanged();
    }

    /**
     * Method to use to update a Transfer's UI
     * 
     * @param file
     *            file to display
     * @param overRelay
     *            is the transfer going over a relay
     */
    public void updateTransfer(Transfer file, boolean overRelay)
    {
        //TODO: use overRelay to indicate slower transfer

        int index = values.indexOf(file);

        if (index < 0)
        {
            notifyDataSetChanged();
            return;
        }

        getView(index, null, null).postInvalidate();
        notifyDataSetChanged();
    }

}

FileUtils 将与您的文件不兼容,因此我将其实现留给您。但它将转移映射到发送它们的联系人。它只是一个实用的 hashmap 助手类 :)

继承人的XML

传入文件.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout1"
    android:layout_width="500dp"
    android:layout_height="200dp" >

    <TextView
        android:id="@+id/incoming_files_subtitle1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:text="@string/incoming_file" />

    <TextView
        android:id="@+id/incoming_files_detail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/incoming_files_subtitle1"
        android:layout_marginLeft="5dp"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/incoming_files_subtitle2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/incoming_files_detail"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="5dp"
        android:text="@string/saved_at" />

    <EditText
        android:id="@+id/incoming_files_path"
        android:layout_width="400dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/incoming_files_subtitle2"
        android:inputType="textUri" />

    <Button
        android:id="@+id/incoming_files_browse"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/incoming_files_path"
        android:layout_toRightOf="@+id/incoming_files_path"
        android:text="@string/browse" />

    <Button
        android:id="@+id/incoming_files_accept"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="2dp"
        android:text="@string/accept" />

    <Button
        android:id="@+id/incoming_files_cancel"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginTop="2dp"
        android:text="@string/cancel" />

</RelativeLayout>

transfer_dialog.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/relativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <LinearLayout 
        android:id="@+id/transfer_button_holder"
        android:orientation="horizontal"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="10dp" >

    <Button 
        android:id="@+id/btn_transfer_incoming"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/incoming"/>

    <Button 
        android:id="@+id/btn_transfer_outgoing"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/outgoing"/>

    <Button 
        android:id="@+id/btn_transfer_finished"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/finished"/>

    <Button 
        android:id="@+id/btn_transfer_all"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/view_all"/>

    </LinearLayout>


    <ListView
        android:id="@+id/transfer_list"
        android:layout_width="fill_parent"
        android:layout_height="650dp"
        android:choiceMode="singleChoice"
        android:layout_below="@+id/transfer_button_holder"
        android:listSelector="@drawable/selector_list" />

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="20dp"
        android:text="@string/cancel" />

</RelativeLayout>

transfer_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/transfer_type"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_gravity="left|center_vertical"
        android:layout_margin="5dp" />

    <TextView
        android:id="@+id/transfer_filename"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/transfer_type"
        android:layout_alignParentTop="true"
        android:gravity="center_horizontal"
        android:text="@string/empty_string" />

    <ProgressBar
        android:id="@+id/transfer_progress"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/transfer_filename"
        android:layout_toRightOf="@+id/transfer_type"
        android:max="100" />

    <TextView
        android:id="@+id/transfer_details"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/transfer_progress"
        android:layout_toRightOf="@+id/transfer_type"
        android:layout_alignParentBottom="true"
        android:text="@string/empty_string" />

</RelativeLayout>

传输对话代码,需要适配:

private void showTransfersDialog()
    {
        transferDialog = new Dialog(context);
        transferDialog.setContentView(R.layout.transfer_dialog);

        transferDialog.setTitle(R.string.transfer_manager);
        transferDialog.setCancelable(true);

        //set up buttons
        Button btnQuit = (Button) transferDialog.findViewById(R.id.btn_cancel);
        Button btnShowIncoming = (Button) transferDialog.findViewById(R.id.btn_transfer_incoming);
        Button btnShowOutgoing = (Button) transferDialog.findViewById(R.id.btn_transfer_outgoing);
        Button btnShowFinished = (Button) transferDialog.findViewById(R.id.btn_transfer_finished);
        Button btnShowAll = (Button) transferDialog.findViewById(R.id.btn_transfer_all);

        transferList = (ListView) transferDialog.findViewById(R.id.transfer_list);
        registerForContextMenu(transferList);
        transferList.setOnItemClickListener(new ListView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                showTransferFileDialog(transferAdapter.getItem(position));
            }
        });
        transferAdapter = new TransferArrayAdapter(SkypeKitVideoDemo.this, android.R.layout.simple_list_item_1,
                FileUtils.getAllTransfersAsList());

        Log.d(LOGTAG, "transferAdapter = " + transferAdapter);

        Log.d(LOGTAG, "setting adapter to transfers = " + transferList);
        transferList.setAdapter(transferAdapter);

        btnQuit.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                transferDialog.dismiss();
                transferDialog = null;
                transferList = null;
            }
        });

        btnShowAll.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                transferAdapter = new TransferArrayAdapter(SkypeKitVideoDemo.this, android.R.layout.simple_list_item_1, FileUtils
                        .getAllTransfersAsList());
                transferList.setAdapter(transferAdapter);
            }
        });

        btnShowIncoming.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                transferAdapter = new TransferArrayAdapter(SkypeKitVideoDemo.this, android.R.layout.simple_list_item_1, FileUtils
                        .getAllTransfersOfTypeAsList(Transfer.Type.INCOMING));
                transferList.setAdapter(transferAdapter);
            }
        });

        btnShowOutgoing.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                transferAdapter = new TransferArrayAdapter(SkypeKitVideoDemo.this, android.R.layout.simple_list_item_1, FileUtils
                        .getAllTransfersOfTypeAsList(Transfer.Type.OUTGOING));
                transferList.setAdapter(transferAdapter);
            }
        });

        btnShowFinished.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                transferAdapter = new TransferArrayAdapter(SkypeKitVideoDemo.this, android.R.layout.simple_list_item_1, FileUtils
                        .getAllFinishedTransfers());
                transferList.setAdapter(transferAdapter);
            }
        });

        //now that the dialog is set up, it's time to show it    
        transferDialog.show();

        return;
    }

传入文件对话框:

private void showIncomingFileDialog(final Conversation convo, final Transfer[] transfers, final int index)
    {
        incomingFileDialog = new Dialog(context);
        incomingFileDialog.setContentView(R.layout.incoming_file);

        if (index >= transfers.length) return;  //sanity check

        String sender = transfers[index].getPartnerHandle();
        String filename = transfers[index].getFileName();

        incomingFileDialog.setTitle("INCOMING FILES(" + (index + 1) + " / " + transfers.length + ") FROM " + sender);
        incomingFileDialog.setCancelable(false);

        //set up controls
        TextView detail = (TextView) incomingFileDialog.findViewById(R.id.incoming_files_detail);
        final EditText pathToFile = (EditText) incomingFileDialog.findViewById(R.id.incoming_files_path);
        Button btnBrowse = (Button) incomingFileDialog.findViewById(R.id.incoming_files_browse);
        Button btnAccept = (Button) incomingFileDialog.findViewById(R.id.incoming_files_accept);
        Button btnCancel = (Button) incomingFileDialog.findViewById(R.id.incoming_files_cancel);
        pathToFile.setText(savingPath + filename);

        detail.setText(filename + "\t- " + FileUtils.getFilesizeFrom(transfers[index]));

        btnAccept.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View arg0)
            {
                float size = Float.parseFloat(transfers[index].getFileSize());

                if (size < getAvailableFreeSpace())
                {
                    transfers[index].accept(pathToFile.getText().toString());
                    FileUtils.addTransferFrom(convo, transfers[index]);
                } else
                    showFileTooBigDialog(convo, transfers[index], pathToFile.getText().toString());

                if (index == transfers.length - 1)
                {
                    incomingFileDialog.dismiss();
                } else
                {
                    incomingFileDialog.dismiss();
                    showIncomingFileDialog(convo, transfers, index + 1);
                }

            }
        });

        btnCancel.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                transfers[index].cancel();
                if (index == transfers.length - 1)
                {
                    incomingFileDialog.dismiss();
                } else
                {
                    incomingFileDialog.dismiss();
                    showIncomingFileDialog(convo, transfers, index + 1);
                }

            }
        });

        btnBrowse.setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                showFolderPicker(convo, transfers, index);
                incomingFileDialog.dismiss();
            }
        });

        //now that the dialog is set up, it's time to show it    
        incomingFileDialog.show();

        return;
    }

这些依赖于 FileUtils,但通过一些努力,您可以将 Conversation 换成 String 并将 Transfer out 换成文件或某种包装器:)

于 2012-11-05T15:52:31.717 回答
1

您不能只更新 in 中的一个ListView项目Android。您应该只更新Adapter正在显示的数据并调用notifyDataSetChanged()您的Adapter.

于 2012-11-04T20:14:37.240 回答