/* * Odoo, Open Source Management Solution * Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http:www.gnu.org/licenses/> * */ package odoo.controls; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Point; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.DragEvent; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.ScrollView; import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import com.odoo.orm.ODataRow; import com.odoo.support.listview.OListAdapter; import com.odoo.support.listview.OListAdapter.OnSearchChange; import com.odoo.R; /** * The Class OList. */ @SuppressLint("ClickableViewAccessibility") public class OList extends ScrollView implements View.OnClickListener, View.OnLongClickListener, View.OnTouchListener, View.OnDragListener, OnSearchChange { /** The Constant KEY_DATA_LOADER. */ private static final String KEY_DATA_LOADER = "data_loader_status"; /** The Constant KEY_CUSTOM_LAYOUT. */ public static final String KEY_CUSTOM_LAYOUT = "custome_layout"; /** The Constant KEY_SHOW_DIVIDER. */ public static final String KEY_SHOW_DIVIDER = "showDivider"; /** The Constant KEY_EMPTY_LIST_MESSAGE. */ public static final String KEY_EMPTY_LIST_MESSAGE = "emptyListMessage"; /** The Constant KEY_EMPTY_LIST_ICON. */ public static final String KEY_EMPTY_LIST_ICON = "emptyListIcon"; /** The Constant KEY_SHOW_AS_CARD. */ public static final String KEY_SHOW_AS_CARD = "showAsCard"; /** The context. */ private Context mContext = null; /** The typed array. */ private TypedArray mTypedArray = null; /** The list adapter. */ private OListAdapter mListAdapter = null; /** The records. */ private List<Object> mRecords = new ArrayList<Object>(); /** The attr. */ private OControlAttributes mAttr = new OControlAttributes(); /** The custom layout. */ private Integer mCustomLayout = 0; /** The inner layout. */ private LinearLayout mInnerLayout = null; /** The layout params. */ private LayoutParams mLayoutParams = null; /** The on row click listener. */ private OnRowClickListener mOnRowClickListener = null; /** The row draggable. */ private Boolean mRowDraggable = false; /** The drag mode. */ private boolean mDragMode = false; /** The drag drop listener. */ private OListDragDropListener mDragDropListener = null; /** The shadow builder. */ private View.DragShadowBuilder mShadowBuilder = null; /** The drop layouts. */ private List<Integer> mDropLayouts = new ArrayList<Integer>(); /** The dropped. */ private Boolean mDropped = false; /** The row droppable. */ private Boolean mRowDroppable = false; /** The draggable view. */ private View mDraggableView = null; /** The drag started. */ private Boolean mDragStarted = false; /** The drag ended. */ private Boolean mDragEnded = false; /** The m view click listener. */ private List<ViewClickListeners> mViewClickListener = new ArrayList<ViewClickListeners>(); /** The m before list row create listener. */ private BeforeListRowCreateListener mBeforeListRowCreateListener = null; /** The on list bottom reached listener. */ private OnListBottomReachedListener mOnListBottomReachedListener = null; /** The record limit. */ private Integer mRecordLimit = -1; /** The record offset. */ private Integer mRecordOffset = 0; /** The display metrics. */ private DisplayMetrics mMetrics = null; /** The scale factor. */ private Float mScaleFactor = 0F; /** The m load new records. */ private Boolean mLoadNewRecords = true; /** The adapter created. */ private Boolean mAdapterCreated = false; /** * Instantiates a new list control. * * @param context * the context */ public OList(Context context) { super(context); init(context, null, 0); } /** * Instantiates a new list control. * * @param context * the context * @param attrs * the attrs */ public OList(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } /** * Instantiates a new list control. * * @param context * the context * @param attrs * the attrs * @param defStyle * the def style */ public OList(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } /** * Inits the list control. * * @param context * the context * @param attrs * the attrs * @param defStyle * the def style */ private void init(Context context, AttributeSet attrs, int defStyle) { mContext = context; mMetrics = getResources().getDisplayMetrics(); mScaleFactor = mMetrics.density; if (attrs != null) { mTypedArray = mContext.obtainStyledAttributes(attrs, R.styleable.OList); mAttr.put(KEY_CUSTOM_LAYOUT, mTypedArray.getResourceId( R.styleable.OList_custom_layout, 0)); mAttr.put(KEY_SHOW_DIVIDER, mTypedArray.getBoolean(R.styleable.OList_showDivider, true)); mAttr.put(KEY_EMPTY_LIST_MESSAGE, mTypedArray.getString(R.styleable.OList_emptyListMessage)); mAttr.put(KEY_EMPTY_LIST_ICON, mTypedArray.getResourceId( R.styleable.OList_emptyListIcon, R.drawable.ic_action_exclamation_mark)); mAttr.put(KEY_SHOW_AS_CARD, mTypedArray.getBoolean(R.styleable.OList_showAsCard, false)); mCustomLayout = mAttr.getResource(KEY_CUSTOM_LAYOUT, 0); mTypedArray.recycle(); } } /* * (non-Javadoc) * * @see android.view.View#onFinishInflate() */ protected void onFinishInflate() { super.onFinishInflate(); removeAllViews(); createListInnerControl(); } /** * Creates the list inner control. */ private void createListInnerControl() { mInnerLayout = parentView(); } /** * Inits the list control. * * @param records * the records */ public void initListControl(List<ODataRow> records) { if (mRecords.size() > 0 && mRecords.size() < records.size()) { List<ODataRow> appendRecords = new ArrayList<ODataRow>(); if (records.size() > 0) { appendRecords.addAll(records.subList(mRecords.size(), records.size())); } appendRecords(appendRecords); } else { if (mRecords.size() != records.size()) { mRecords.clear(); mRecords.addAll(records); createAdapter(); } else { mLoadNewRecords = false; removeDataLoaderProgress(); } } if (!mAdapterCreated) { createAdapter(); } if (mRecords.size() <= 0) { showEmptyListView(); } } private void removeDataLoaderProgress() { if (findViewWithTag(KEY_DATA_LOADER) != null) { int index = mInnerLayout .indexOfChild(findViewWithTag(KEY_DATA_LOADER)); mInnerLayout.removeViewAt(index); } } /** * Append records. * * @param newRecords * the new records */ public void appendRecords(List<ODataRow> newRecords) { if (newRecords.size() > 0) { int lastPosition = mRecords.size(); mRecords.addAll(lastPosition, newRecords); mListAdapter.notifiyDataChange(mRecords); addRecordViews(lastPosition, -1); } else { mLoadNewRecords = false; removeDataLoaderProgress(); } } /** * Append records at position. * * @param index * the index * @param newRecords * the new records */ public void appendRecords(Integer index, List<ODataRow> newRecords) { if (newRecords.size() > 0) { mRecords.addAll(index, newRecords); mListAdapter.notifiyDataChange(mRecords); int end_index = newRecords.size() + 1; addRecordViews(index, end_index); } else { mLoadNewRecords = false; removeDataLoaderProgress(); } } /** * Creates the adapter. */ @SuppressLint("NewApi") private void createAdapter() { mListAdapter = new OListAdapter(mContext, mCustomLayout, mRecords) { @Override public View getView(final int position, View convertView, ViewGroup parent) { View mView = (View) convertView; LayoutInflater inflater = LayoutInflater.from(mContext); if (mView == null) { mView = inflater.inflate(getResource(), parent, false); } final ODataRow record = (ODataRow) mRecords.get(position); final OForm form = (OForm) mView; for (final ViewClickListeners listener : mViewClickListener) { for (final String key : listener.getKeys()) { OForm.OnViewClickListener itemClick = new OForm.OnViewClickListener() { @Override public void onFormViewClick(View view, ODataRow row) { listener.getListener(key).onRowViewClick(form, view, position, row); } }; if (form.findViewById(listener.getViewId(key)) instanceof OField) { OField field = (OField) form.findViewById(listener .getViewId(key)); field.setOnItemClickListener(itemClick); } else { form.setOnViewClickListener( listener.getViewId(key), itemClick); } } } form.initForm(record); if (mBeforeListRowCreateListener != null) { mBeforeListRowCreateListener.beforeListRowCreate(position, record, mView); } return mView; } }; mListAdapter.setOnSearchChange(this); mAdapterCreated = true; addRecordViews(0, -1); } /** * Sets the empty list message. * * @param message * the new empty list message */ public void setEmptyListMessage(String message) { mAttr.put(KEY_EMPTY_LIST_MESSAGE, message); } /** * Sets the empty list icon. * * @param icon * the new empty list icon */ public void setEmptyListIcon(Integer icon) { mAttr.put(KEY_EMPTY_LIST_ICON, icon); } /** * Show empty list view. */ private void showEmptyListView() { mInnerLayout.removeAllViews(); LinearLayout mEmptyListLayout = new LinearLayout(mContext); mEmptyListLayout.setOrientation(LinearLayout.VERTICAL); Integer padding = (int) (20 * mScaleFactor); mLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); mEmptyListLayout.setLayoutParams(mLayoutParams); mEmptyListLayout.setPadding(padding, padding * 4, padding, padding); mEmptyListLayout.setGravity(Gravity.CENTER); // Adding empty list icon ImageView imgIcon = new ImageView(mContext); int height = (int) (96 * mScaleFactor); mLayoutParams = new LayoutParams(height, height); imgIcon.setLayoutParams(mLayoutParams); imgIcon.setImageResource(mAttr.getResource(KEY_EMPTY_LIST_ICON, R.drawable.ic_action_exclamation_mark)); imgIcon.setColorFilter(mContext.getResources().getColor( R.color.gray_light)); mEmptyListLayout.addView(imgIcon); // Adding empty message TextView txvEmptyMessage = new TextView(mContext); mLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); txvEmptyMessage.setLayoutParams(mLayoutParams); txvEmptyMessage.setTextAppearance(mContext, android.R.style.TextAppearance_Large); txvEmptyMessage.setTypeface(OControlHelper.boldFont()); txvEmptyMessage.setGravity(Gravity.CENTER); txvEmptyMessage.setTextColor(mContext.getResources().getColor( R.color.gray_light)); String empty_message = mAttr.getString(KEY_EMPTY_LIST_MESSAGE, "No records found"); txvEmptyMessage.setText(empty_message); mEmptyListLayout.addView(txvEmptyMessage); mInnerLayout.addView(mEmptyListLayout); } /** * Adds the record views. */ private void addRecordViews(Integer start, Integer end) { if (start == 0 && end == -1) { removeAllViews(); mInnerLayout.removeAllViews(); addView(mInnerLayout); } else { mInnerLayout = (LinearLayout) findViewWithTag("list_parent_view"); removeDataLoaderProgress(); } if (end == -1) { end = mListAdapter.getCount(); } int listLen = mListAdapter.getCount(); for (int i = start; i < end; i++) { OForm view = (OForm) mListAdapter.getView(i, null, null); view.setTag(i); if (mOnRowClickListener != null) { view.setOnClickListener(this); } if (mRowDraggable) { view.setOnLongClickListener(this); view.setOnTouchListener(this); view.setOnDragListener(this); } if (mRowDroppable) { view.setOnDragListener(this); } if (mAttr.getBoolean(KEY_SHOW_AS_CARD, false)) { ViewGroup card = cardOuterView(i); card.addView(view); if (end == listLen) mInnerLayout.addView(card); else mInnerLayout.addView(card, i); mInnerLayout .setBackgroundResource(R.color.card_view_parent_background); setBackgroundResource(R.color.card_view_parent_background); } else { mInnerLayout.addView(view); if (mAttr.getBoolean(KEY_SHOW_DIVIDER, true)) { if (end == listLen) mInnerLayout.addView(divider()); else mInnerLayout.addView(divider(), i); } } } } /** * Show as card. * * @param showAsCard * the show as card */ public void showAsCard(boolean showAsCard) { mAttr.put(KEY_SHOW_AS_CARD, showAsCard); } /** * Card outer view. * * @return the view */ private LinearLayout cardOuterView(int position) { LinearLayout cardView = new LinearLayout(mContext); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); int left_right_margin = (int) (10 * mScaleFactor); int top_margin = (int) (6 * mScaleFactor); if (position == mListAdapter.getCount() - 1) { params.setMargins(left_right_margin, top_margin, left_right_margin, left_right_margin); } else { params.setMargins(left_right_margin, top_margin, left_right_margin, 0); } cardView.setLayoutParams(params); int padding = (int) (2 * mScaleFactor); cardView.setPadding(padding, padding, padding, padding); cardView.setOrientation(LinearLayout.VERTICAL); cardView.setBackgroundResource(R.drawable.card); return cardView; } /** * Parent view. * * @return the linear layout */ private LinearLayout parentView() { LinearLayout mLayout = new LinearLayout(mContext); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); mLayout.setLayoutParams(params); mLayout.setOrientation(LinearLayout.VERTICAL); mLayout.setTag("list_parent_view"); return mLayout; } /** * Divider. * * @return the view */ private View divider() { View v = new View(mContext); v.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 1)); v.setBackgroundColor(mContext.getResources().getColor( R.color.list_divider)); return v; } /** * Sets the custom view. * * @param view_resource * the new custom view */ public void setCustomView(int view_resource) { mAttr.put(KEY_CUSTOM_LAYOUT, view_resource); mCustomLayout = view_resource; } /** * Sets the on row click listener. * * @param listener * the new on row click listener */ public void setOnRowClickListener(OnRowClickListener listener) { mOnRowClickListener = listener; } /** * The listener interface for receiving onRowClick events. The class that is * interested in processing a onRowClick event implements this interface, * and the object created with that class is registered with a component * using the component's <code>addOnRowClickListener<code> method. When * the onRowClick event occurs, that object's appropriate * method is invoked. * * @see OnRowClickEvent */ public interface OnRowClickListener { /** * On row item click. * * @param position * the position * @param view * the view * @param row * the row */ public void onRowItemClick(int position, View view, ODataRow row); } /* * (non-Javadoc) * * @see android.view.View.OnClickListener#onClick(android.view.View) */ @Override public void onClick(View v) { if (!mDragMode) { int pos = (Integer) v.getTag(); mOnRowClickListener.onRowItemClick(pos, v, (ODataRow) mRecords.get(pos)); } } /** * Sets the drag drop listener. * * @param listener * the new drag drop listener */ public void setDragDropListener(OListDragDropListener listener) { mDragDropListener = listener; } /* * (non-Javadoc) * * @see android.view.View.OnLongClickListener#onLongClick(android.view.View) */ @Override public boolean onLongClick(View v) { mDragMode = true; mDragStarted = false; mDragEnded = false; return true; } /** * The Class DragShadowBuilder. */ private static class DragShadowBuilder extends View.DragShadowBuilder { /** The shadow. */ private static Drawable shadow; /** The height. */ int width, height; /** * Instantiates a new drag shadow builder. * * @param v * the v */ public DragShadowBuilder(View v) { super(v); shadow = new ColorDrawable(Color.LTGRAY); width = getView().getWidth() / 2; height = getView().getHeight() / 2; } /* * (non-Javadoc) * * @see * android.view.View.DragShadowBuilder#onProvideShadowMetrics(android * .graphics.Point, android.graphics.Point) */ @Override public void onProvideShadowMetrics(Point size, Point touch) { shadow.setBounds(0, 0, width, height); size.set(width, height); touch.set(width / 2, height / 2); } /* * (non-Javadoc) * * @see * android.view.View.DragShadowBuilder#onDrawShadow(android.graphics * .Canvas) */ @Override public void onDrawShadow(Canvas canvas) { shadow.draw(canvas); } } /** * Sets the row draggable. * * @param draggable * the new row draggable */ public void setRowDraggable(boolean draggable) { mRowDraggable = draggable; } /* * (non-Javadoc) * * @see android.view.View.OnTouchListener#onTouch(android.view.View, * android.view.MotionEvent) */ @Override public boolean onTouch(View v, MotionEvent event) { if (mDragMode && event.getAction() == MotionEvent.ACTION_MOVE) { mShadowBuilder = new DragShadowBuilder(v); v.startDrag(null, mShadowBuilder, v, 0); v.setVisibility(View.INVISIBLE); return true; } return false; } /* * (non-Javadoc) * * @see android.view.View.OnDragListener#onDrag(android.view.View, * android.view.DragEvent) */ @Override public boolean onDrag(final View v, DragEvent event) { int action = event.getAction(); final View view = (View) event.getLocalState(); ViewGroup parent = (ViewGroup) view.getParent(); ViewGroup newParent = (ViewGroup) v; final int position = (Integer) view.getTag(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: if (mRowDraggable && mDragDropListener != null) onDragStart(view, position, mRecords.get(position)); break; case DragEvent.ACTION_DRAG_ENTERED: if (mRowDroppable || isDroppable(v)) v.setBackgroundColor(Color.GRAY); break; case DragEvent.ACTION_DRAG_EXITED: if (mRowDroppable || isDroppable(v)) v.setBackgroundColor(Color.WHITE); break; case DragEvent.ACTION_DROP: if (mRowDroppable || isDroppable(v)) { parent.removeView(view); view.setVisibility(View.VISIBLE); view.setOnTouchListener(null); newParent.setBackgroundColor(Color.WHITE); if (getDraggableView() instanceof OList) { int drop_position = (Integer) newParent.getTag(); OList draggableView = (OList) getDraggableView(); draggableView.setDroppedObjectData(view, position, mRecords.get(drop_position)); } if (getDraggableView() == null && isDroppable(v)) { // Adding view to layout newParent.addView(view); } } mDragMode = false; mDropped = true; break; case DragEvent.ACTION_DRAG_ENDED: if (!mDropped) { view.post(new Runnable() { @Override public void run() { view.setVisibility(View.VISIBLE); } }); } if (mDragDropListener != null) { onDragEnnd(view, position, mRecords.get(position)); } mDragMode = false; mDropped = false; break; } return true; } /** * Sets the dropped object data. * * @param view * the view * @param position * the position * @param object * the object */ public void setDroppedObjectData(View view, int position, Object object) { if (mDragDropListener != null) { mDragDropListener.onItemDrop(view, mRecords.get(position), object); } } /** * On drag start. * * @param view * the view * @param position * the position * @param object * the object */ private void onDragStart(View view, int position, Object object) { if (!mDragStarted) { mDragDropListener.onItemDragStart(view, position, object); mDragStarted = true; } } /** * On drag ennd. * * @param view * the view * @param position * the position * @param object * the object */ private void onDragEnnd(View view, int position, Object object) { if (!mDragEnded) { mDragDropListener.onItemDragEnd(view, position, mRecords.get(position)); mDragEnded = true; } } /** * Sets the row droppable. * * @param droppable * the droppable * @param draggableView * the draggable view */ public void setRowDroppable(boolean droppable, View draggableView) { mRowDroppable = droppable; mDraggableView = draggableView; } /** * Adds the drop listener layout. * * @param resource * the resource */ public void addDropListenerLayout(int resource) { mDropLayouts.add(resource); ViewGroup view = (ViewGroup) getParent(); View droppable_view = view.findViewById(resource); droppable_view.setTag("droppable_view"); droppable_view.setOnDragListener(this); } /** * Checks if is droppable. * * @param v * the v * @return true, if is droppable */ public boolean isDroppable(View v) { if (v.getTag() != null && v.getTag().toString().equals("droppable_view")) return true; return false; } /** * Gets the draggable view. * * @return the draggable view */ public View getDraggableView() { return mDraggableView; } /** * Sets the on list row view click listener. * * @param view_id * the view_id * @param listener * the listener */ public void setOnListRowViewClickListener(Integer view_id, OnListRowViewClickListener listener) { mViewClickListener.add(new ViewClickListeners(view_id, listener)); } /** * Sets the before list row create listener. * * @param callback * the new before list row create listener */ public void setBeforeListRowCreateListener( BeforeListRowCreateListener callback) { mBeforeListRowCreateListener = callback; } /** * Sets the on list bottom reached listener. * * @param listener * the new on list bottom reached listener */ public void setOnListBottomReachedListener( OnListBottomReachedListener listener) { mOnListBottomReachedListener = listener; } /** * Sets the record offset. * * @param offset * the offset * @return the o list */ public OList setRecordOffset(Integer offset) { mRecordOffset = offset; return this; } /** * Sets the record limit. * * @param limit * the limit * @return the o list */ public OList setRecordLimit(Integer limit) { mRecordLimit = limit; return this; } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mLoadNewRecords && getViewVisiblityDiff() == 0 && mOnListBottomReachedListener != null) { if (mOnListBottomReachedListener.showLoader()) { LinearLayout loaderLayout = new LinearLayout(mContext); mLayoutParams = new LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); // Adding loader progress ProgressBar mProgress = new ProgressBar(mContext); loaderLayout.setGravity(Gravity.CENTER); loaderLayout.addView(mProgress); loaderLayout.setPadding(15, 15, 15, 15); loaderLayout.setTag(KEY_DATA_LOADER); mInnerLayout.addView(loaderLayout); post(new Runnable() { @Override public void run() { fullScroll(ScrollView.FOCUS_DOWN); } }); } mOnListBottomReachedListener.onBottomReached(mRecordLimit, mRecordOffset); } } /** * Gets the view visiblity diff. * * @return the view visiblity diff */ private Integer getViewVisiblityDiff() { View view = (View) getChildAt(getChildCount() - 1); if (view.findViewWithTag(KEY_DATA_LOADER) != null) return -1; return (view.getBottom() - (getHeight() + getScrollY())); } /** * Gets the query listener. * * @return the query listener */ public OnQueryTextListener getQueryListener() { return mQueryListener; } @Override public void onSearchChange(List<Object> newRecords) { if (findViewWithTag(KEY_DATA_LOADER) != null) { removeView(findViewWithTag(KEY_DATA_LOADER)); } mRecords.clear(); mRecords.addAll(newRecords); addRecordViews(0, -1); if (mRecords.size() <= 0) { showEmptyListView(); } } /** The query listener. */ private OnQueryTextListener mQueryListener = new OnQueryTextListener() { private boolean isSearched = false; @Override public boolean onQueryTextChange(String newText) { if (TextUtils.isEmpty(newText)) { newText = ""; if (isSearched && mListAdapter != null) { mListAdapter.getFilter().filter(null); } } else { isSearched = true; mListAdapter.getFilter().filter(newText); } return false; } @Override public boolean onQueryTextSubmit(String query) { return false; } }; /** * The listener interface for receiving onListRowViewClick events. The class * that is interested in processing a onListRowViewClick event implements * this interface, and the object created with that class is registered with * a component using the component's * <code>addOnListRowViewClickListener<code> method. When * the onListRowViewClick event occurs, that object's appropriate * method is invoked. * * @see OnListRowViewClickEvent */ public interface OnListRowViewClickListener { /** * On row view click. * * @param view_group * the view_group * @param view * the view * @param position * the position * @param row * the row */ public void onRowViewClick(ViewGroup view_group, View view, int position, ODataRow row); } /** * The Class ViewClickListeners. */ private class ViewClickListeners { /** The _listener_data. */ private HashMap<String, OnListRowViewClickListener> _listener_data = new HashMap<String, OnListRowViewClickListener>(); /** The _listener_view. */ private HashMap<String, Integer> _listener_view = new HashMap<String, Integer>(); /** * Instantiates a new view click listeners. * * @param view_id * the view_id * @param listener * the listener */ public ViewClickListeners(Integer view_id, OnListRowViewClickListener listener) { String key = "KEY_" + view_id; _listener_data.put(key, listener); _listener_view.put(key, view_id); } /** * Gets the listener. * * @param key * the key * @return the listener */ public OnListRowViewClickListener getListener(String key) { return _listener_data.get(key); } /** * Gets the view id. * * @param key * the key * @return the view id */ public Integer getViewId(String key) { return _listener_view.get(key); } /** * Gets the keys. * * @return the keys */ public List<String> getKeys() { List<String> keys = new ArrayList<String>(); keys.addAll(_listener_view.keySet()); return keys; } } /** * The listener interface for receiving beforeListRowCreate events. The * class that is interested in processing a beforeListRowCreate event * implements this interface, and the object created with that class is * registered with a component using the component's * <code>addBeforeListRowCreateListener<code> method. When * the beforeListRowCreate event occurs, that object's appropriate * method is invoked. * * @see BeforeListRowCreateEvent */ public interface BeforeListRowCreateListener { /** * Before list row create. * * @param position * the position * @param view * the view */ public void beforeListRowCreate(int position, ODataRow row, View view); } /** * The listener interface for receiving onListBottomReached events. The * class that is interested in processing a onListBottomReached event * implements this interface, and the object created with that class is * registered with a component using the component's * <code>addOnListBottomReachedListener<code> method. When * the onListBottomReached event occurs, that object's appropriate * method is invoked. * * @see OnListBottomReachedEvent */ public interface OnListBottomReachedListener { /** * On bottom reached. * * @param record_limit * the record_limit * @param record_offset * the record_offset */ public void onBottomReached(Integer record_limit, Integer record_offset); /** * Show loader. * * @return the boolean */ public Boolean showLoader(); } }