How to Create a Closed (Circular) Listview

Closed or circular Horizontal ListView Android

As per your requirement you want circular/infinite scrolling horizontal list view,

This is InfiniteScrollView which may help.You need to update this library as per your requirement and change ImageView to any other view which you want to scroll horizontally.

Edit - Solution below works for scrolling list view circularly only on one side ::

Check this circular-list for implementing a circular list adapter. And as your list view is horizontal check this library to create a custom horizontal list view.

Happy Coding :)

Closed or circular Vertical ListView Android

public class MainActivity extends Activity {
ListView list;
long startTime;
long endTime;


List<String> mList = new ArrayList<String>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView) findViewById(R.id.list);
downloadDetails();

String str;
for (int i = 0; i < 10; i++) {
str = new String("Data --- " + i);
mList.add(str);
}
CircularAdapter adapter = new CircularAdapter(this, 0, mList);
list.setAdapter(adapter);
final YourRunnable runy = new YourRunnable();

list.setOnTouchListener(new OnTouchListener() {

@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {

startTime = (new Date()).getTime();
runy.onPause();// pausing thread actually pauses scrolling
}
if (event.getAction() == MotionEvent.ACTION_UP) {
endTime = (new Date()).getTime();
if ((endTime - startTime) <= 100) {// 100 mill second limit
// for click

// Log.i("ITEM CLICK() ", "item : ");
}

runy.onResume(); // resume scrolling
}

return false;
}

});

new Thread(runy).start();

}





class YourRunnable implements Runnable {
private Object mPauseLock;
private boolean mPaused;
private boolean mFinished;

public YourRunnable() {
mPauseLock = new Object();
mPaused = false;
mFinished = false;
}

@SuppressLint("NewApi")
public void run() {
while (!mFinished) {
// for loop is not infinite but enough as Integer.MAX_VALUE
for (int index = 0; index < list.getAdapter().getCount(); index++) {
list.smoothScrollToPositionFromTop(list.getLastVisiblePosition() + 1, 0, 10000);
try {
// it helps scrolling to stay smooth as possible (by
// experiment)
Thread.sleep(3000);
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();// putting thread in wait
// list of mPauseLock
// object
} catch (InterruptedException e) {
}
}
}
} catch (Exception e) {
e.printStackTrace();
}

}

}
}

// to pause list
public void onPause() {
synchronized (mPauseLock) {
mPaused = true;
}
}

// resume thread
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();// notify all object that are waiting on
// the wait list of mPauseLock object
}
}

}

private class CircularAdapter extends ArrayAdapter {

List<String> mlist;
Context mContext;
LayoutInflater inflater;
public final int HALF_MAX_VALUE = Integer.MAX_VALUE / 2;
public final int MIDDLE;

@SuppressWarnings("unchecked")
public CircularAdapter(Context ctx, int resId, List<String> objects) {
super(ctx, resId, objects);
mContext = ctx;
mlist = objects;
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % mlist.size();

}

@Override
public int getCount() {
// TODO Auto-generated method stub
return Integer.MAX_VALUE;
}

@Override
public String getItem(int position) {
// TODO Auto-generated method stub
int relativePos = position % mlist.size();
Log.i("RELATIVE : ", " POS:" + relativePos);
return mlist.get(relativePos);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder holder = null;

if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item, parent, false);
holder.name = (TextView) convertView.findViewById(R.id.name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}

String model = getItem(position);
holder.name.setText(model);

convertView.setOnClickListener(new ListenerT(model) {

@Override
public void onClick(View v) {
Log.i("CLICK", "ITEM---" + name);

}
});

return convertView;

}

}

// use your own listener to pass parameter
private class ListenerT implements OnClickListener {

String name;

public ListenerT(String nm) {
name = nm;
}

@Override
public void onClick(View v) {

}

}

private class ViewHolder {
TextView name;
}

}

Circular (or infinite) listview with ArrayAdapter

It looks like your main issue is how you are referencing the items. You can't use items.get(position) because position is going to overflow. Try adding these methods to your adapter:

@Override
public int getCount() {
return Integer.MAX_VALUE;
}

@Override
public Item getItem(int position) {
return items.get(position % items.size());
}

And replace

final Item i = items.get(position); 

with

final Item i = getItem(position);

Circular ListView (Items on Half Circle)

So when I made the sample app to demo this I had to do 2 things.

First, was edit the onDraw(Canvas) on my custom view. This could be any view, I make it a TextView for simplicity. This allows me to push the view over based on an equation.

public class MyView extends TextView {

private static final int MAX_INDENT = 300;
private static final String TAG = MyView.class.getSimpleName();

public MyView(Context context) {
super(context);
}

public void onDraw(Canvas canvas){
canvas.save();
float indent = getIndent(getY());
canvas.translate(indent, 0);
super.onDraw(canvas);
canvas.restore();
}

public float getIndent(float distance){
float x_vertex = MAX_INDENT;
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
float y_vertex = displayMetrics.heightPixels / 2 / displayMetrics.density;
double a = ( 0 - x_vertex ) / ( Math.pow(( 0 - y_vertex), 2) ) ;
float indent = (float) (a * Math.pow((distance - y_vertex), 2) + x_vertex);
return indent;
}
}

The second thing I had to do was to Override the ListView class, make it implement OnScrollListener and call setOnScrollListener(this);. Now I am able to scroll through the list, it follows the equation that I put in the view.

public class HalfCircleListView extends ListView implements AbsListView.OnScrollListener {
public HalfCircleListView(Context context) {
super(context);
setOnScrollListener(this);
}


@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
//Ignored
}

@Override
public void onScroll(AbsListView absListView, int i, int i2, int i3) {
absListView.invalidateViews();
}
}

You can download the full source from my Gist.

Initial State
Initial State of the View
Scrolled State
Scrolled to the bottom

As you can see my math is a little off... I use a parabola vs a circle, so that will have to be changed.

Circular ListView (like a carousel way)

Doing some research, I found the effect what I want (carousel) using ListViews but with another name: Circular ListView in another question in this forum that is suitable and its results are what I expected.

Here is the link to the answer:
How to create a closed (circular) ListView?

Thanks for viewing and contribute for solutions!!!

How to create a circular ListView?

I think Android SDK: Creating a Rotating Dialer will help you to create your layout.

You have to modify code yourself to achieve your goal. May be this is a good start for you. :)

Sample Image

How to create circular list view of items in android?

You need to check this library : WheelView

add dependency to your build.gradle

dependencies {
compile 'com.github.lukedeighton:wheelview:0.3.1'
}

add custom view to your xml

<com.lukedeighton.wheelview.WheelView
android:id="@+id/wheelview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:wheelColor="@color/grey_400"
app:rotatableWheelDrawable="false"
app:selectionAngle="90.0"
app:wheelPosition="bottom"
app:wheelOffsetY="60dp"
app:repeatItems="true"
app:wheelRadius="276dp"
app:wheelItemCount="14"
app:wheelPadding="13dp"
app:wheelItemRadius="43dp"/>

set adapter in java code

wheelView.setAdapter(new WheelAdapter() {
@Override
public Drawable getDrawable(int position) {
//return drawable here - the position can be seen in the gifs above
}

@Override
public int getCount() {
//return the count
}
});

Sample Image



Related Topics



Leave a reply



Submit