Skip to content

Instantly share code, notes, and snippets.

@libinbensin
Created May 9, 2014 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save libinbensin/9fff896d5d234e8209c4 to your computer and use it in GitHub Desktop.
Save libinbensin/9fff896d5d234e8209c4 to your computer and use it in GitHub Desktop.
HorizontalListView to add items horizontally
import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Adapter;
import android.widget.BaseAdapter;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
/**
* A custom widget to display the list items in horizontal direction
* <p/>
* Do not try to add view directly to this HorizontalListView,
* as HorizontalScrollView supports only one child Layout.
* <p/>
* Created by libin on 5/8/14.
*/
public class HorizontalListView extends HorizontalScrollView implements View.OnClickListener {
private final Context mContext;
/**
* layout to hold list items
*/
private LinearLayout mParent;
/**
* listener for list item click
*/
private OnItemClickListener mOnItemClickListener;
/**
* adapter to fill data to list items
*/
private BaseAdapter mAdapter;
/**
* Data observer to listener for change in the adapter data
*/
AbstractDataSetObserver mDataSetObserver;
/**
* Simple constructor to use when creating a view from code.
*
* @param context The content which the view is running in ,
* through which can access the themes , resources , etc.
*/
public HorizontalListView(Context context) {
super(context);
this.mContext = context;
}
/**
* Constructor that is called when inflating a view from XML.
* A Child layout is added to the parent View, to hold the list items.
*
* @param context The content which the view is running in ,
* through which can access the themes , resources , etc.
* @param attrs The attributes of the XML tag that is inflating the view.
*/
public HorizontalListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
/**
* Sets the adapter to this HorizontalListView
*
* @param adapter an adapter which provides item data
*/
public void setAdapter(BaseAdapter adapter) {
// unregister the old data observer
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
mDataSetObserver = null;
}
// set the adapter
mAdapter = adapter;
// register the new data observer
if (mAdapter != null) {
mDataSetObserver = new AbstractDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
}
// refresh the layout
refreshLayout();
}
/**
* Get the adapter set to this HorizontalListView
*
* @return the adapter
*/
public Adapter getAdapter() {
return mAdapter;
}
/**
* Clear the list items
*/
public void clear() {
if(this.mParent != null) {
mParent.removeAllViewsInLayout();
}
}
/**
* refresh the list with new items from adapter
*/
void refreshLayout() {
// remove all the existing items
if(this.mParent != null) {
this.removeAllViewsInLayout();
}
// re initialize the parent view
this.mParent = new LinearLayout(mContext);
int itemCount = mAdapter.getCount();
int index = 0;
while (index < itemCount) {
View child = obtainView(index);
if (child != null) {
// add the child to parent
addItemView(child, index);
index++;
}
}
// add the parent view
this.addView(mParent);
}
/**
* add view items to HorizontalListView
*
* @param child the child view
* @param index index of the child view
*/
private void addItemView(View child, int index) {
setupItemView(child, index);
this.mParent.addView(child, index);
}
private void setupItemView(View view, int index) {
// set some default padding
view.requestFocusFromTouch();
view.setPadding(2, 0, 2, 0);
view.setOnClickListener(this);
view.setTag(index);
}
private View obtainView(int position) {
View child = mAdapter.getView(position, null, this);
return child;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mAdapter != null && mDataSetObserver == null) {
mDataSetObserver = new AbstractDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
mDataSetObserver = null;
}
this.mOnItemClickListener = null;
}
/**
* Sets an listener for HorizontalListView items clicks
*
* @param listener an OnItemClickListener
*/
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}
/**
* An method invoked when an item in HorizontalListView is clicked
*
* @param view
*/
@Override
public void onClick(View view) {
if (this.mOnItemClickListener != null) {
this.mOnItemClickListener.onItemClick(view, (Integer) view.getTag());
}
}
/**
* An interface to handle the HorizontalListView item ClickListener
*/
public static interface OnItemClickListener {
public void onItemClick(View view, int position);
}
/**
* An data observer to listener for the change in the adapter data
*/
private class AbstractDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
super.onChanged();
// refresh the view
refreshLayout();
}
@Override
public void onInvalidated() {
super.onInvalidated();
// refresh the view
refreshLayout();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment