我尝试做一个视图来显示多个文件下载。 ProgressDialog非常适合显示单个文件下载信息,但我认为它不能用作ListView的元素或以某种方式设置多个文件指示(或者可以吗?)
所以我实现自己的适配器,如this等一些指南所示,它可以正常工作,我可以添加下载项目(TextView的名称+ ProgressBar,最大值设置为文件大小),但是如何更新ProgressBar项目清单?
如果这是一种不好的做法,哪种方式最好显示多个文件下载进度?
download_item.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;
}
}
DownloadAdapter类
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;
}
}
DownloadView类
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));
}
}
答案 0 :(得分: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
incoming_file.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并转出文件或某种包装器:)
答案 1 :(得分:1)
您无法仅更新ListView
中Android
中的某个项目。您应该只更新Adapter
正在显示的数据,并在notifyDataSetChanged()
上致电Adapter
。