java – 在onScroll上添加和删除水平列表项

weixin_38097536 2019-09-12 02:06:07
我需要显示无限滚动的水平列表视图项(意味着需要重复项目),例如 A,B,C,d,E,F,A,B,C,d,E,F,A,B,…. Bolded是屏幕上的可见项目 该过程是在到达最后一个列表项后重复列表项,我尝试在滚动列表时添加列表项,以便我自定义水平列表视图类.但是在右边添加列表项后滚动到左边,我得到ArrayIndexOutOfBoundsException.我试图在基本适配器中添加Integer.MAX VALUE选项以获得无限的项目但是在定位项目时没有帮助(set selection()).如果有人知道如何添加和删除水平列表项,请分享.
...全文
37 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38120359 2019-09-12
  • 打赏
  • 举报
回复
而不是扩展BaseAdapter扩展ArrayAdapter. 解决方法1 :: 注意:::在AgarwalActivity.java中为水平列表视图创建布尔变量isHorizo​​ntalListView = true. Horizo​​ntalListView.java public class HorizontalListView extends AdapterView<ListAdapter> { public boolean mAlwaysOverrideTouch = true; protected ListAdapter mAdapter; private int mLeftViewIndex = -1; private int mRightViewIndex = 0; protected int mCurrentX; protected int mNextX; private int mMaxX = Integer.MAX_VALUE; private int mDisplayOffset = 0; protected Scroller mScroller; private GestureDetector mGesture; private Queue<View> mRemovedViewQueue = new LinkedList<View>(); private OnItemSelectedListener mOnItemSelected; private OnItemClickListener mOnItemClicked; private OnItemLongClickListener mOnItemLongClicked; private boolean mDataChanged = false; public HorizontalListView(Context context, AttributeSet attrs) { super(context, attrs); initView(); } private synchronized void initView() { mLeftViewIndex = -1; mRightViewIndex = 0; mDisplayOffset = 0; mCurrentX = 0; mNextX = 0; mMaxX = Integer.MAX_VALUE; mScroller = new Scroller(getContext()); mGesture = new GestureDetector(getContext(), mOnGesture); } @Override public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) { mOnItemSelected = listener; } @Override public void setOnItemClickListener(AdapterView.OnItemClickListener listener){ mOnItemClicked = listener; } @Override public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) { mOnItemLongClicked = listener; } private DataSetObserver mDataObserver = new DataSetObserver() { @Override public void onChanged() { synchronized(HorizontalListView.this){ mDataChanged = true; } invalidate(); requestLayout(); } @Override public void onInvalidated() { reset(); invalidate(); requestLayout(); } }; @Override public ListAdapter getAdapter() { return mAdapter; } @Override public View getSelectedView() { //TODO: implement return null; } @Override public void setAdapter(ListAdapter adapter) { if(mAdapter != null) { mAdapter.unregisterDataSetObserver(mDataObserver); } mAdapter = adapter; mAdapter.registerDataSetObserver(mDataObserver); reset(); } private synchronized void reset(){ initView(); removeAllViewsInLayout(); requestLayout(); } @Override public void setSelection(int position) { //TODO: implement } private void addAndMeasureChild(final View child, int viewPos) { LayoutParams params = child.getLayoutParams(); if(params == null) { params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); } addViewInLayout(child, viewPos, params, true); child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); } @Override protected synchronized void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if(mAdapter == null){ return; } if(mDataChanged){ int oldCurrentX = mCurrentX; initView(); removeAllViewsInLayout(); mNextX = oldCurrentX; mDataChanged = false; } if(mScroller.computeScrollOffset()){ int scrollx = mScroller.getCurrX(); mNextX = scrollx; } if(mNextX <= 0){ mNextX = 0; mScroller.forceFinished(true); } if(mNextX >= mMaxX) { mNextX = mMaxX; mScroller.forceFinished(true); } int dx = mCurrentX - mNextX; removeNonVisibleItems(dx); fillList(dx); positionItems(dx); mCurrentX = mNextX; if(!mScroller.isFinished()){ post(new Runnable() { public void run() { // TODO Auto-generated method stub requestLayout(); } }); } } private void fillList(final int dx) { int edge = 0; View child = getChildAt(getChildCount()-1); if(child != null) { edge = child.getRight(); } fillListRight(edge, dx); edge = 0; child = getChildAt(0); if(child != null) { edge = child.getLeft(); } fillListLeft(edge, dx); } private void fillListRight(int rightEdge, final int dx) { while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) { View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this); addAndMeasureChild(child, -1); rightEdge += child.getMeasuredWidth(); if(mRightViewIndex == mAdapter.getCount()-1) { mMaxX = mCurrentX + rightEdge - getWidth(); } if (mMaxX < 0) { mMaxX = 0; } mRightViewIndex++; } } private void fillListLeft(int leftEdge, final int dx) { while(leftEdge + dx > 0 && mLeftViewIndex >= 0) { View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this); addAndMeasureChild(child, 0); leftEdge -= child.getMeasuredWidth(); mLeftViewIndex--; mDisplayOffset -= child.getMeasuredWidth(); } } private void removeNonVisibleItems(final int dx) { View child = getChildAt(0); while(child != null && child.getRight() + dx <= 0) { mDisplayOffset += child.getMeasuredWidth(); mRemovedViewQueue.offer(child); removeViewInLayout(child); mLeftViewIndex++; child = getChildAt(0); } child = getChildAt(getChildCount()-1); while(child != null && child.getLeft() + dx >= getWidth()) { mRemovedViewQueue.offer(child); removeViewInLayout(child); mRightViewIndex--; child = getChildAt(getChildCount()-1); } } private void positionItems(final int dx) { if(getChildCount() > 0){ mDisplayOffset += dx; int left = mDisplayOffset; for(int i=0;i<getChildCount();i++){ View child = getChildAt(i); int childWidth = child.getMeasuredWidth(); child.layout(left, 0, left + childWidth, child.getMeasuredHeight()); left += childWidth; } } } public synchronized void scrollTo(int x) { mScroller.startScroll(mNextX, 0, x - mNextX, 0); requestLayout(); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { boolean handled = super.dispatchTouchEvent(ev); handled |= mGesture.onTouchEvent(ev); return handled; } protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { synchronized(HorizontalListView.this){ mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0); } requestLayout(); return true; } protected boolean onDown(MotionEvent e) { mScroller.forceFinished(true); return true; } private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { return HorizontalListView.this.onDown(e); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { synchronized(HorizontalListView.this){ mNextX += (int)distanceX; } requestLayout(); return true; } @Override public boolean onSingleTapConfirmed(MotionEvent e) { for(int i=0;i<getChildCount();i++){ View child = getChildAt(i); if (isEventWithinView(e, child)) { if(mOnItemClicked != null){ mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i )); } if(mOnItemSelected != null){ mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i )); } break; } } return true; } @Override public void onLongPress(MotionEvent e) { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (isEventWithinView(e, child)) { if (mOnItemLongClicked != null) { mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i)); } break; } } } private boolean isEventWithinView(MotionEvent e, View child) { Rect viewRect = new Rect(); int[] childPosition = new int[2]; child.getLocationOnScreen(childPosition); int left = childPosition[0]; int right = left + child.getWidth(); int top = childPosition[1]; int bottom = top + child.getHeight(); viewRect.set(left, top, right, bottom); return viewRect.contains((int) e.getRawX(), (int) e.getRawY()); } }; } AgarwalActivity.java public class AgarwalActivity extends Activity{ private LayoutInflater _inflater; private ListView listView; private HorizontalListView hListView; private RankingsAdapter rankingsAdapter; private boolean isHorizontalListView = false; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(isHorizontalListView){ setContentView(R.layout.listviewdemo); hListView = (HorizontalListView) findViewById(R.id.listview); }else{ setContentView(R.layout.listview); listView=(ListView)findViewById(R.id.listView); } ArrayList<String> rankingArrayList = new ArrayList<String>(); for(int i=0;i<25;i++) rankingArrayList.add("agarwal"+i); _inflater= LayoutInflater.from(AgarwalActivity.this); rankingsAdapter = new RankingsAdapter(AgarwalActivity.this,R.id.text,rankingArrayList); if(isHorizontalListView) hListView.setAdapter(rankingsAdapter); else listView.setAdapter(rankingsAdapter); } private class RankingsAdapter extends ArrayAdapter<String>{ private ArrayList<String> _row_list; public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2; public final int MIDDLE; public RankingsAdapter(Context context,int textViewResourceId,ArrayList<String> arrL) { // TODO Auto-generated constructor stub super(context,textViewResourceId, arrL); _row_list = arrL; MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % _row_list.size(); } public int getCount() { // TODO Auto-generated method stub return Integer.MAX_VALUE; } public String getItem(int position) { // TODO Auto-generated method stub return _row_list.get(position % _row_list.size()); } public long getItemId(int position) { // TODO Auto-generated method stub return position % _row_list.size(); } public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub ViewHolder holder = null; if(convertView == null){ holder = new ViewHolder(); convertView = (LinearLayout)_inflater.inflate(R.layout.text_layout, null); //getting the IDs holder.driver = (TextView)convertView.findViewById(R.id.text); convertView.setTag(holder); } else { holder=(ViewHolder)convertView.getTag(); } //Settng bean values to row components holder.driver.setText(_row_list.get(position % _row_list.size())); return convertView; }//getView() class ViewHolder{ //holding the components TextView driver; }//ViewHolder--Class inside CountriesAdapter }//RankingsAdapter-inner class }//AgarwalActivity-class listview.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </RelativeLayout> listviewdemo.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#fff" > <com.vl.agarwal.HorizontalListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ddd" /> </LinearLayout> text_layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:minHeight="?android:attr/listPreferredItemHeight" android:paddingLeft="6dip" android:textAppearance="?android:attr/textAppearanceLarge" /> </LinearLayout> ————————————————– ———————————– Solution2 ::将库用作水平列表视图 row.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/itemtext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:textColor="@android:color/white" android:textStyle="bold" android:textSize="30sp"/> </LinearLayout> main.xml中 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <Gallery android:id="@+id/horizontallistview" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> AgarwalActivity.java public class AgarwalActivity extends Activity { Gallery myHorizontalListView; private RankingsAdapter rankingsAdapter; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ArrayList<String> rankingArrayList = new ArrayList<String>(); for(int i=0;i<25;i++) rankingArrayList.add("agarwal"+i); DisplayMetrics metrics = new DisplayMetrics(); this.getWindowManager().getDefaultDisplay().getMetrics(metrics); myHorizontalListView = (Gallery)findViewById(R.id.horizontallistview); MarginLayoutParams mlp = (MarginLayoutParams) myHorizontalListView.getLayoutParams(); mlp.setMargins(-(metrics.widthPixels/2), mlp.topMargin, mlp.rightMargin, mlp.bottomMargin ); rankingsAdapter = new RankingsAdapter(AgarwalActivity.this,R.id.itemtext,rankingArrayList); myHorizontalListView.setAdapter(rankingsAdapter); myHorizontalListView.setSelection(10,true); myHorizontalListView.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Toast.makeText( AgarwalActivity.this, parent.getItemAtPosition(position).toString() + " Clicked", Toast.LENGTH_LONG) .show(); }}); } private class RankingsAdapter extends ArrayAdapter<String>{ private ArrayList<String> _row_list; public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2; public final int MIDDLE; public RankingsAdapter(Context context,int textViewResourceId,ArrayList<String> arrL) { // TODO Auto-generated constructor stub super(context,textViewResourceId, arrL); _row_list = arrL; MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % _row_list.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 return _row_list.get(position % _row_list.size()); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position % _row_list.size(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub View rowView = LayoutInflater .from(parent.getContext()) .inflate(R.layout.row, null); TextView listTextView = (TextView)rowView.findViewById(R.id.itemtext); listTextView.setText(_row_list.get(position % _row_list.size())); return rowView; }//getView() }//RankingsAdapter-inner class }//AgarwalActivity-class

433

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧