как создать закрытый (круговой) listview?

<p>я хочу создать собственный listview (или аналогичный), который будет вести себя как закрытый (круговой):</p><ol> <li>прокрутка вниз - после того, как последний элемент был достигнут, начинается первый (.., n-1, n, 1, 2, ..)</li> <li>прокрутка вверх - после достижения первого элемента начинается последний (.., 2, 1, n, n-1, ..)</li> </ol><p>концептуально это звучит просто, но, по-видимому, не существует прямого подхода к этому. кто-нибудь может указать мне правильное решение? спасибо !</p><p>я уже получил ответ (от streets of boston на google-разработчиках android-групп), но это звучит как-то некрасиво :) -</p><blockquote> <p>я сделал это, создав свой собственный список-адаптер (подкласс из baseadapter).</p> <p>я кодировал свой собственный список-адаптер таким образом, чтобы его метод getcount () возвращал число huuuuge.</p> <p>и если выбран элемент 'x', то этот элемент соответствует позиции адаптера = 'adapter.getcount ()/2 + x'</p> <p>и для метода моего адаптера getitem (int position) я смотрю в своем массиве, который создает резервную копию адаптера, и извлекаю элемент по индексу: (position-getcount ()/2)% mydataitems.length</p> <p>вам нужно сделать еще несколько "специальных" вещей, чтобы все это работало правильно, но вы поняли идею.</p> <p>в принципе, все еще возможно достичь конца или начала списка, но если вы установите для getcount () около миллиона или около того, это трудно сделать :-)</p> </blockquote>

<p>мой коллега джо, и я считаю, что мы нашли более простой способ решить ту же проблему. в нашем решении вместо расширения baseadapter мы расширяем arrayadapter.</p><p>код как пара:</p><pre><code> 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]; } } </code></pre><p>таким образом, создается класс с именем circulararrayadapter, который принимает тип объекта t (который может быть любым) и использует его для создания списка массивов. t обычно является строкой, хотя может быть чем угодно.</p><p>конструктор такой же, как и для arrayadapter, но инициализирует константу с именем middle. это середина списка. независимо от того, какую длину массива middle можно использовать для центрирования listview в середине списка.</p><p>getcount переопределяется, чтобы вернуть огромное значение, как это было сделано выше при создании огромного списка.</p><p>getitem переопределяется, чтобы вернуть поддельную позицию в массиве. таким образом, при заполнении списка список заполняется объектами циклично.</p><p>на этом этапе circulararrayadapter просто заменяет arrayadapter в файле, создающем listview.</p><p>чтобы центрировать listview, в файл необходимо вставить следующую строку, создающую listview после инициализации объекта listview:</p><p><code>listviewobject.setselectionfromtop(nameofadapterobject.middle, 0);</code></p><p>и используя константу middle, предварительно инициализированную для списка, представление центрируется с верхним элементом списка в верхней части экрана.</p><p>:) ~ cheers, я надеюсь, что это решение полезно.</p>

<p>решение, которое вы упоминаете, - это то, которое я сказал другим разработчикам использовать в прошлом. в getcount () просто верните integer.max\_value, он даст вам около 2 миллиардов элементов, чего должно быть достаточно.</p>

<p>я сделал, или я думаю, что я сделал это правильно, основываясь на ответах выше. надеюсь, что это поможет вам.</p><pre><code>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; } } </code></pre><p>и вы хотели бы сделать это, если вы хотите прокрутить список вниз. обычно мы можем просто прокрутить список вверх, а затем прокрутить вниз.</p><p>// посмотрим, сколько предметов мы бы хотели прокрутить. в этом случае integer.max\_value</p><pre><code>int listviewlength = adapter.getcount(); // see how many items a screen can dispaly, i use variable "span" final int span = recipelistview.getlastvisibleposition() - recipelistview.getfirstvisibleposition(); </code></pre><p>// посмотрим, сколько у нас страниц</p><pre><code>int howmanyspans = listviewlength / span; </code></pre><p>// увидеть, где вы хотите быть, когда запустите просмотр списка. вы не должны делать вещи "-3". это для моего приложения, чтобы работать правильно.</p><pre><code>recipelistview.setselection((span * (howmanyspans / 2)) - 3); </code></pre>

<p>при использовании loaderscallbacks я создал класс mycircularcursor, который оборачивает типичный курсор следующим образом</p><pre><code>@override public void onloadfinished(loader<cursor> pcursorloader, cursor pcursor) { mitemlistadapter.swapcursor(new mycircularcursor(pcursor)); } </code></pre><p>код класса декоратора находится здесь:</p><pre class="lang-java prettyprint-override"><code>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); } } </code></pre>

<p>я мог бы найти некоторые хорошие ответы на это, один из моих <a href="https://stackoverflow.com/users/421372/ragunath-jawahar">друг</a> пытался достичь этого с помощью простого решения. проверьте проект <a href="https://github.com/ragunathjawahar/circular-list-adapter">github</a> .</p>