我想创建一个自定义的ListView(或类似的),它的行为就像一个封闭的(圆形的):
在概念上听起来很简单,但显然,没有直接的方法来做到这一点。 谁能指出我正确的解决方案? 谢谢!
我已经收到了答案(来自Streets Of Boston的Android-Developers google群组),但听起来有些丑陋:) -
我是通过自己创造的 list-adapter(子类) BaseAdapter)。
我在这样的代码中编写了自己的列表适配器 它的getCount()方法返回的方式 一个HUUUUGE号码。
如果选择了项目'x',那么这个 item对应适配器 位置= 'adapter.getCount()/ 2 + X'
对于我的适配器的方法 getItem(int position),我看着我 备份适配器的数组 获取索引上的项目: (position-getCount()/ 2)%myDataItems.length
你需要做一些'特别' 东西,使一切正常, 但是你明白了。
原则上,仍有可能 到达结束或开始 列表,但是如果你将getCount()设置为 大约一百万左右,这很难 做: - )
答案 0 :(得分:84)
我的同事乔,我相信我们找到了一种更简单的方法来解决同样的问题。在我们的解决方案中,我们扩展了ArrayAdapter而不是扩展BaseAdapter。
代码就是休闲:
public class CircularArrayAdapter extends ArrayAdapter
{
public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
public final int MIDDLE;
private T[] objects;
public CircularArrayAdapter(Context context, int textViewResourceId, T[] objects)
{
super(context, textViewResourceId, objects);
this.objects = objects;
MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % objects.length;
}
@Override
public int getCount()
{
return Integer.MAX_VALUE;
}
@Override
public T getItem(int position)
{
return objects[position % objects.length];
}
}
因此,这会创建一个名为CircularArrayAdapter的类,它接受一个对象类型T(可能是任何东西)并使用它来创建一个数组列表。 T通常是一个字符串,但可能是任何东西。
构造函数与ArrayAdapter的构造函数相同,但初始化一个名为middle的常量。这是列表的中间部分。无论MIDDLE数组的长度如何都可以用于将ListView置于列表中间。
getCount被覆盖以返回一个巨大的值,就像创建一个巨大的列表一样。
getItem被覆盖以返回数组上的假位置。因此,当填充列表时,列表以循环方式填充对象。
此时,CircularArrayAdapter只是在创建ListView的文件中替换ArrayAdapter。
要使ListView居中,必须在初始化ListView对象后创建ListView的文件中插入以下行:
listViewObject.setSelectionFromTop(nameOfAdapterObject.MIDDLE, 0);
并使用先前为列表初始化的MIDDLE常量,视图以屏幕顶部列表的顶部项目为中心。
:)〜干杯,我希望这个解决方案很有用。
答案 1 :(得分:13)
你提到的解决方案是我告诉其他开发人员过去使用的解决方案。在getCount()中,只需返回Integer.MAX_VALUE,它将为您提供大约20亿个项目,这应该足够了。
答案 2 :(得分:8)
根据上面的答案,我有,或者我认为我做得对。 希望这会帮助你。
private static class RecipeListAdapter extends BaseAdapter {
private static LayoutInflater mInflater;
private Integer[] mCouponImages;
private static ImageView viewHolder;
public RecipeListAdapter(Context c, Integer[] coupomImages) {
RecipeListAdapter.mInflater = LayoutInflater.from(c);
this.mCouponImages = coupomImages;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object getItem(int position) {
// you can do your own tricks here. to let it display the right item in your array.
return position % mCouponImages.length;
}
@Override
public long getItemId(int position) {
return position;
// return position % mCouponImages.length;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.coupon_list_item, null);
viewHolder = (ImageView) convertView.findViewById(R.id.item_coupon);
convertView.setTag(viewHolder);
} else {
viewHolder = (ImageView) convertView.getTag();
}
viewHolder.setImageResource(this.mCouponImages[position % mCouponImages.length]);
return convertView;
}
}
如果你想向下滚动列表,你想这样做。 通常我们可以向上滚动并列出然后向下滚动。
//查看我们想要滚动的项目数量。在这种情况下,Integer.MAX_VALUE
int listViewLength = adapter.getCount();
// see how many items a screen can dispaly, I use variable "span"
final int span = recipeListView.getLastVisiblePosition() - recipeListView.getFirstVisiblePosition();
//查看我们有多少页
int howManySpans = listViewLength / span;
//在启动列表视图时查看您想要的位置。你不必做“-3”的事情。 这是我的应用程序正常工作。
recipeListView.setSelection((span * (howManySpans / 2)) - 3);
答案 3 :(得分:1)
答案 4 :(得分:1)
如果使用LoadersCallbacks,我创建了MyCircularCursor类,它包装了这样的典型光标:
@Override
public void onLoadFinished(Loader<Cursor> pCursorLoader, Cursor pCursor) {
mItemListAdapter.swapCursor(new MyCircularCursor(pCursor));
}
装饰器类代码在这里:
public class MyCircularCursor implements Cursor {
private Cursor mCursor;
public MyCircularCursor(Cursor pCursor) {
mCursor = pCursor;
}
@Override
public int getCount() {
return mCursor.getCount() == 0 ? 0 : Integer.MAX_VALUE;
}
@Override
public int getPosition() {
return mCursor.getPosition();
}
@Override
public boolean move(int pOffset) {
return mCursor.move(pOffset);
}
@Override
public boolean moveToPosition(int pPosition) {
int position = MathUtils.mod(pPosition, mCursor.getCount());
return mCursor.moveToPosition(position);
}
@Override
public boolean moveToFirst() {
return mCursor.moveToFirst();
}
@Override
public boolean moveToLast() {
return mCursor.moveToLast();
}
@Override
public boolean moveToNext() {
if (mCursor.isLast()) {
mCursor.moveToFirst();
return true;
} else {
return mCursor.moveToNext();
}
}
@Override
public boolean moveToPrevious() {
if (mCursor.isFirst()) {
mCursor.moveToLast();
return true;
} else {
return mCursor.moveToPrevious();
}
}
@Override
public boolean isFirst() {
return false;
}
@Override
public boolean isLast() {
return false;
}
@Override
public boolean isBeforeFirst() {
return false;
}
@Override
public boolean isAfterLast() {
return false;
}
@Override
public int getColumnIndex(String pColumnName) {
return mCursor.getColumnIndex(pColumnName);
}
@Override
public int getColumnIndexOrThrow(String pColumnName) throws IllegalArgumentException {
return mCursor.getColumnIndexOrThrow(pColumnName);
}
@Override
public String getColumnName(int pColumnIndex) {
return mCursor.getColumnName(pColumnIndex);
}
@Override
public String[] getColumnNames() {
return mCursor.getColumnNames();
}
@Override
public int getColumnCount() {
return mCursor.getColumnCount();
}
@Override
public byte[] getBlob(int pColumnIndex) {
return mCursor.getBlob(pColumnIndex);
}
@Override
public String getString(int pColumnIndex) {
return mCursor.getString(pColumnIndex);
}
@Override
public short getShort(int pColumnIndex) {
return mCursor.getShort(pColumnIndex);
}
@Override
public int getInt(int pColumnIndex) {
return mCursor.getInt(pColumnIndex);
}
@Override
public long getLong(int pColumnIndex) {
return mCursor.getLong(pColumnIndex);
}
@Override
public float getFloat(int pColumnIndex) {
return mCursor.getFloat(pColumnIndex);
}
@Override
public double getDouble(int pColumnIndex) {
return mCursor.getDouble(pColumnIndex);
}
@Override
public int getType(int pColumnIndex) {
return 0;
}
@Override
public boolean isNull(int pColumnIndex) {
return mCursor.isNull(pColumnIndex);
}
@Override
public void deactivate() {
mCursor.deactivate();
}
@Override
@Deprecated
public boolean requery() {
return mCursor.requery();
}
@Override
public void close() {
mCursor.close();
}
@Override
public boolean isClosed() {
return mCursor.isClosed();
}
@Override
public void registerContentObserver(ContentObserver pObserver) {
mCursor.registerContentObserver(pObserver);
}
@Override
public void unregisterContentObserver(ContentObserver pObserver) {
mCursor.unregisterContentObserver(pObserver);
}
@Override
public void registerDataSetObserver(DataSetObserver pObserver) {
mCursor.registerDataSetObserver(pObserver);
}
@Override
public void unregisterDataSetObserver(DataSetObserver pObserver) {
mCursor.unregisterDataSetObserver(pObserver);
}
@Override
public void setNotificationUri(ContentResolver pCr, Uri pUri) {
mCursor.setNotificationUri(pCr, pUri);
}
@Override
public boolean getWantsAllOnMoveCalls() {
return mCursor.getWantsAllOnMoveCalls();
}
@Override
public Bundle getExtras() {
return mCursor.getExtras();
}
@Override
public Bundle respond(Bundle pExtras) {
return mCursor.respond(pExtras);
}
@Override
public void copyStringToBuffer(int pColumnIndex, CharArrayBuffer pBuffer) {
mCursor.copyStringToBuffer(pColumnIndex, pBuffer);
}
}