Programing

닫힌 (원형) ListView를 만드는 방법은 무엇입니까?

lottogame 2020. 12. 24. 23:21
반응형

닫힌 (원형) ListView를 만드는 방법은 무엇입니까?


닫힌 (원형) 것처럼 동작하는 사용자 정의 ListView (또는 이와 유사한)를 만들고 싶습니다.

  1. 아래로 스크롤-마지막 항목에 도달 한 후 첫 번째 시작 (.., n-1, n, 1, 2, ..)
  2. 위로 스크롤-첫 번째 항목에 도달 한 후 마지막 시작 (.., 2, 1, n, n-1, ..)

개념적으로는 간단하게 들리지만이 작업을 수행하는 직접적인 방법은 없습니다. 누구든지 저에게 올바른 솔루션을 알려줄 수 있습니까? 감사합니다 !

나는 이미 (Android-Developers Google 그룹의 Streets Of Boston에서) 답변을 받았지만 어떻게 든 추악하게 들립니다. :)-

내 자신의 목록 어댑터 (BaseAdapter에서 서브 클래 싱)를 만들어이를 수행했습니다.

getCount () 메서드가 HUUUUGE 번호를 반환하는 방식으로 내 목록 어댑터를 코딩했습니다.

그리고 만약 'x'항목이 선택되면이 항목은 adapter position = 'adapter.getCount () / 2 + x'에 해당합니다.

그리고 내 어댑터의 메소드 getItem (int position)의 경우 어댑터를 백업하고 인덱스에서 항목을 가져 오는 배열을 살펴 봅니다. (position-getCount () / 2) % myDataItems.length

모든 것이 올바르게 작동하도록하려면 좀 더 '특별한'작업을 수행해야하지만 아이디어를 얻을 수 있습니다.

원칙적으로 목록의 끝이나 시작에 도달하는 것은 여전히 ​​가능하지만 getCount ()를 약 백만 정도 설정하면 수행하기가 어렵습니다. :-)


제 동료 인 Joe와 저는 동일한 문제를 해결하는 더 간단한 방법을 찾았다 고 생각합니다. 솔루션에서는 BaseAdapter를 확장하는 대신 ArrayAdapter를 확장합니다.

코드는 다음과 같습니다.

public class CircularArrayAdapter< T > extends ArrayAdapter< T >
{   

        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];
        }
 }

따라서 이것은 객체 유형 T (무엇이든 될 수 있음)를 취하고이를 사용하여 배열 목록을 생성하는 CircularArrayAdapter라는 클래스를 생성합니다. T는 일반적으로 문자열이지만 무엇이든 될 수 있습니다.

생성자는 middle이라는 상수를 초기화하지만 ArrayAdapter의 경우와 동일합니다. 이것은 목록의 중간입니다. 배열의 길이에 관계없이 MIDDLE을 사용하여 ListView를 목록의 중앙에 배치 할 수 있습니다.

getCount() 거대한 목록을 만드는 위에서 수행 한 것처럼 큰 값을 반환하는 재정의입니다.

getItem()배열의 가짜 위치를 반환하는 재정의입니다. 따라서 목록을 채울 때 목록은 반복되는 방식으로 객체로 채워집니다.

이 시점에서 CircularArrayAdapter는 ListView를 만드는 파일에서 ArrayAdapter를 대체합니다.

ListView를 중앙에 배치하려면 ListView 개체가 초기화 된 후 ListView를 만드는 파일에 다음 줄을 삽입해야합니다.

listViewObject.setSelectionFromTop(nameOfAdapterObject.MIDDLE, 0);

목록에 대해 이전에 초기화 된 MIDDLE 상수를 사용하면보기가 화면 상단에 목록의 최상위 항목과 함께 중앙에 배치됩니다.

:) ~ 건배,이 솔루션이 유용하기를 바랍니다.


당신이 언급 한 해결책은 제가 과거에 다른 개발자들에게 사용하라고 말한 것입니다. getCount ()에서 간단히 Integer.MAX_VALUE를 반환하면 약 20 억 개의 항목이 제공되므로 충분합니다.


위의 답변을 기반으로했거나 올바르게 수행했다고 생각합니다. 이것이 당신을 도울 수 있기를 바랍니다.

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);

나는 이것에 대한 좋은 대답을 볼 수 있었다. 내 친구 중 한 명이 간단한 해결책을 통해 이것을 달성하려고 노력했다. github 프로젝트를 확인하십시오 .


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);
}
}

참조 URL : https://stackoverflow.com/questions/2332847/how-to-create-a-closed-circular-listview

반응형