• ListView中开发问题汇总


    android中ListView使用最为频繁,但是同时出现问题也是最多的,下面就总结一下我在开发中遇到的问题,

    问题一:在自定义添加adapter中添加button,或是checkBox时无法同时响应setOnItemClickListener事件中的item click 事件和控件本身点击事件

    item 原布局文件;


    <?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="wrap_content"
    	>
    	<Button
    		android:id="@+id/array_button"
    		android:layout_width="wrap_content" 
    		android:layout_height="wrap_content"
    	    android:text="一个按钮"
    	  
    	/>
    	<ImageView android:id="@+id/array_image"
    		android:layout_toRightOf="@+id/array_button"
    		android:layout_width="wrap_content" android:layout_height="fill_parent"
    		android:layout_alignParentTop="true" android:layout_alignParentBottom="true"
    		android:adjustViewBounds="true"
    		android:padding="2dip" />
    	<TextView android:id="@+id/array_title"
    		android:layout_width="fill_parent" android:layout_height="wrap_content"
    		android:layout_toRightOf="@+id/array_image"
    		android:layout_alignParentBottom="true"
    		android:layout_alignParentRight="true" android:singleLine="true"
    		android:ellipsize="marquee" 
    		android:textSize="15dip"  />
    	<TextView android:id="@+id/array_text"
    		android:layout_width="fill_parent" android:layout_height="wrap_content"
    		android:layout_toRightOf="@+id/array_image"
    		android:layout_below="@+id/array_title"
    		android:layout_alignParentBottom="true"
    		android:layout_alignParentRight="true" 
    		android:singleLine="true"
    		android:ellipsize="marquee" 
    		android:textSize="20dip" />
    
    
    </RelativeLayout>
    


    重写的adapter:

    public View getView(final int position, View convertView, ViewGroup parent) {
    	    ImageView iamge = null;
    	    TextView title = null;
    	    TextView text = null;
    	    Button button = null;
    	    if (convertView == null) {
    		convertView = LayoutInflater.from(mContext).inflate(
    			mTextViewResourceID, null);
    		iamge = (ImageView) convertView.findViewById(R.id.array_image);
    		title = (TextView) convertView.findViewById(R.id.array_title);
    		text = (TextView) convertView.findViewById(R.id.array_text);
    		button = (Button)convertView.findViewById(R.id.array_button);
    		button.setOnClickListener(new OnClickListener() {
    		    
    		    @Override
    		    public void onClick(View arg0) {
    			Toast.makeText(arrayList,"您点击的第"+position +"个按钮", Toast.LENGTH_LONG).show();
    			
    		    }
    		});
    	    }
    	    
    	}


    解决方法:只要在item布局文件中添加 android:descendantFocusability="blocksDescendants" 属性,

    在添加的控件添加属性

    android:clickable="true"
     android:focusable="false"

    更改后的item布局文件内容:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    	android:layout_width="fill_parent" android:layout_height="wrap_content"
    	android:descendantFocusability="blocksDescendants">
    	<Button
    		android:id="@+id/array_button"
    		android:layout_width="wrap_content" 
    		android:layout_height="wrap_content"
    	    android:text="一个按钮"
    	    android:clickable="true"
    	    android:focusable="false"
    	/>
    	<ImageView android:id="@+id/array_image"
    		android:layout_toRightOf="@+id/array_button"
    		android:layout_width="wrap_content" android:layout_height="fill_parent"
    		android:layout_alignParentTop="true" android:layout_alignParentBottom="true"
    		android:adjustViewBounds="true"
    		android:padding="2dip" />
    	<TextView android:id="@+id/array_title"
    		android:layout_width="fill_parent" android:layout_height="wrap_content"
    		android:layout_toRightOf="@+id/array_image"
    		android:layout_alignParentBottom="true"
    		android:layout_alignParentRight="true" android:singleLine="true"
    		android:ellipsize="marquee" 
    		android:textSize="15dip"  />
    	<TextView android:id="@+id/array_text"
    		android:layout_width="fill_parent" android:layout_height="wrap_content"
    		android:layout_toRightOf="@+id/array_image"
    		android:layout_below="@+id/array_title"
    		android:layout_alignParentBottom="true"
    		android:layout_alignParentRight="true" 
    		android:singleLine="true"
    		android:ellipsize="marquee" 
    		android:textSize="20dip" />
    
    </RelativeLayout>

    问题二:如何再点击item时获取item内子对象,根据适当条件改变其属性内容

    例如单击item选项后改变这条item背景色

    解决方法:使用adapterView.getChildAt(index)方法

    mListView.setOnItemClickListener(new OnItemClickListener() {
    	    @Override
    	    public void onItemClick(AdapterView<?> adapterView, View view, int position,
    		    long id) {
    		View v=adapterView.getChildAt(position);
    		v.setBackgroundColor(Color.RED);
    		
    	    }
    	});

    看上去好像可以了,但是以上方法只是用于数据没有滚动时即可见区域内

    当数据量很大时,即开始滑动是再点击会发生adapterView.getChildAt(index)获取view为空

    这时就需要另一个方法adapterView.getFirstVisiblePosition();获取第一个可见item位置,使用当前position-这个位置

    具体实现View v=adapterView.getChildAt(pos-adapterView.getFirstVisiblePosition());


    判断adapter内数据第一次出现加载:

    根据getView中的position判断是否大于mLastAnimatedPosition,如果大于mLastAnimatedPosition则为第一次

    private int mLastAnimatedPosition= -1;
    	boolean firstLoadData(int pos){
    		boolean isFirst=false;
    		if(pos>mLastAnimatedPosition){
    			isFirst=true;
    			this.mLastAnimatedPosition=pos;
    		}
    		return isFirst;
    	}

    Listview 定位,恢复ListView上次的视图位置:

    ListView mListView;
    	int backIndex,backTop;
    	//保存item view  index,偏移量
    	void saveListViewPositionView(){
    		backIndex=mListView.getFirstVisiblePosition();
    		View v=mListView.getChildAt(0);
    		backTop=(v==null) ? 0:v.getTop();
    	}
    	//根据上次保存index,偏移量恢复视图
    	void restoreListViewPositionView(){
    		mListView.setSelectionFromTop(backIndex, backTop);
    	}

    其实还可以使用setSelection也可以定位,只是setSelectionFromTop要比setSelection更精准。因为通过getFirstVisiblePosition得到的第一个item可能已经有一部分是不可见的了,如果用setSelection无法反映出这不可见的部分。

    还可以使用带有滚动过程带有动画效果方式:

    mListView.smoothScrollBy("distance",duration);
    mListView.smoothScrollToPosition(position);


    Listview 添加HeaderView时,设置指定大小值:

    ImageView imageHeaderView = new ImageView(this);
    imageHeaderView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.deckblatt));
    imageHeaderView.setScaleType(ScaleType.CENTER_CROP);
    imageHeaderView.setLayoutParams(new AbsListView.LayoutParams(100, 100));  
    myList.addHeaderView(imageHeaderView);

    值得注意的LayoutParams必须为AbsListView.LayoutParams才能生效,不然程序奔溃,无效。

    HeaderView设置隐藏时Gone还会有占位,需要remove或者增加了一个多余的Layout(item_container)来囊括item内部控件。此时,如果在item_container .setVisibility(View.GONE)则可以完美实现隐藏HeaderView的目的!


    ListView设置Selector为空

    mListView.setSelector(null);//空指针

    mListView.setSelector(newColorDrawable(Color.TRANSPARENT));


    ListView及item焦点问题:

    mListView.requestFocusFromTouch();

    這時你需要在你的xml文件中对些控件添加android:focusable=false;

    ListView的右边滚动滑块启用

    使用XML布局只需要在 ListView节点中加入 android:fastScrollEnabled="true" 这个属性即可,

    而对于Java代码可以通过myListView.setFastScrollEnabled(true); 来控制启用,参数false为隐藏。
     还有一点就是当你的滚动内容较小,不到当前ListView的3个屏幕高度时则不会出现这个



    listview 中几个实用的属性:

    去掉ListView Selector选种时黄色底纹一闪的效果

    <?xmlversion="1.0" encoding="utf-8"?>

    <shapexmlns:android="http://schemas.android.com/apk/res/android">

        <solidandroid:color="@android:color/transparent"/>

        <cornersandroid:radius="0dip" />   

    </shape>

    //listview.setSelector(R.drawable.thisShape);


    Listview右边滚动条始终显示

     xml文件中做如下修改   android:fadeScrollbars="false"

    stackFromBottom属性,这只该属性之后你做好的列表就会显示你列表的最下面,值为true和false
    android:stackFromBottom="true"             

    transciptMode属性,需要用ListView或者其它显示大量Items的控件实时跟踪或者查看信息,并且希望最新的条目可以自动滚动到可视范围内。通过设置的控件transcriptMode属性可以将Android平台的控件(支持ScrollBar)自动滑动到最底部。
     android:transcriptMode="alwaysScroll"    

    cacheColorHint属性,很多人希望能够改变一下它的背景,使他能够符合整体的UI设计,改变背景背很简单只需要准备一张图片然后指定属性 android:background="@drawable/bg",不过不要高兴地太早,当你这么做以后,发现背景是变了,但是当你拖动,或者点击list空白位置的时候发现ListItem都变成黑色的了,破坏了整体效果。

    如果你只是换背景的颜色的话,可以直接指定android:cacheColorHint为你所要的颜色,如果你是用图片做背景的话,那也只要将android:cacheColorHint指定为透明(#00000000)就可以了

    divider属性,该属性作用是每一项之间需要设置一个图片做为间隔,或是去掉item之间的分割线
    android:divider="@drawable/list_driver"  其中  @drawable/list_driver 是一个图片资源,如果不想显示分割线则只要设置为android:divider="@drawable/@null" 就可以了

    fadingEdge属性,上边和下边有黑色的阴影
    android:fadingEdge="none" 设置后没有阴影了~

     scrollbars属性,作用是隐藏listView的滚动条,
    android:scrollbars="none"与setVerticalScrollBarEnabled(true);的效果是一样的,不活动的时候隐藏,活动的时候也隐藏

    fadeScrollbars属性,android:fadeScrollbars="true"  配置ListView布局的时候,设置这个属性为true就可以实现滚动条的自动隐藏和显示。


    LIstView局部刷新View处理:(How can I update a single row in a ListView?)

    private void updateItemView(int index,boolean selected){
            View vitem = mListView.getChildAt(index -
                    mListView.getFirstVisiblePosition());
            CheckBox checkStore=(CheckBox)vitem.findViewById(R.id.shop_title_checkbox);
            checkStore.setChecked(selected);
    		vitem.invalidate();
        }


    控制listview滚动速度

    // scroll speed decreases as friction increases. a value of 2 worked
        getListView().setFriction(ViewConfiguration.getScrollFriction() * 2);

        //  因子越大滚动越慢 ,只有API>11时可以使用(Verified that this works really nicely for API >= 11:)


    headerView or footview问题

    在添加和删除HeaderView之前,先执行mListView.setAdapter()不然报错,这个问题在低于4.0以前版本会有这个问题,4.0之后在哪里add都可以

    headerView or footview 在设置为gone时还会有展位情况,解决方法:反复执行remove,add,这样在一定程度上影响效率,可以在嵌套一层可以解决

    <?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="wrap_content"
        android:orientation="vertical" >
    
        <!-- @color/shop_cart_order_pref_bg_color -->
    
        <RelativeLayout
            android:id="@+id/rl"
            android:layout_width="match_parent"
            android:layout_height="40dip"
            android:gravity="center_vertical"
            android:paddingLeft="10dp"
            android:paddingRight="10dp" >
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:drawablePadding="5dp"
                android:drawableRight="@drawable/jiantou"
                android:text="@string/nologin_tipe"
                android:textColor="#999999"
                android:textSize="12sp" />
        </RelativeLayout>
    
    </LinearLayout>
    
    操作里面的id=rl布局gone即可占位消除(此问题也可用于解决listview 中的item部分内容隐藏占位问题)
    

    速度计算处理方式 (1,GestureDetector.SimpleOnGestureListener onFling处理,也可以使用速度计算VelocityTracker实现)

    VelocityTrackingTouchListener mTouchListener;
    	    GestureDetector mGestureDetector;
    	    void initTouchLis(View v){
    	    	// Instantiate a gesture listener to consume scroll and fling events
    	    	FlingDetector flingDetector = new FlingDetector();
    	    	// Pass the FlingDetector to mGestureDetector to receive the appropriate callbacks
    	    	mGestureDetector = new GestureDetector(this, flingDetector);
    	    	mTouchListener = new VelocityTrackingTouchListener();
    	    	v.setOnTouchListener(mTouchListener);
    	    }
    	    
    	    class VelocityTrackingTouchListener implements View.OnTouchListener {
    	    	private VelocityTracker mVelocityTracker;
    			private int mPointerId;
    			private float xVelocity,yVelocity;
    			
    	        @Override
    	        public boolean onTouch(View view, MotionEvent motionEvent) {
    	        	switch (motionEvent.getAction()) {
    		            case MotionEvent.ACTION_DOWN:
    		                if (mVelocityTracker == null) {
    		                    // Retrieve a new VelocityTracker object to watch the velocity of a motion.
    		                    mVelocityTracker = VelocityTracker.obtain();
    		                } else {
    		                    // Reset the velocity tracker back to its initial state.
    		                    mVelocityTracker.clear();
    		                }
    		                // Add a user's movement to the tracker.
    		                mVelocityTracker.addMovement(motionEvent);
    		        		//求第一个触点的id, 此时可能有多个触点,但至少一个 
    		               mPointerId = motionEvent.getPointerId(0); 
    		            break;
    		            case MotionEvent.ACTION_MOVE:
    		                mVelocityTracker.addMovement(motionEvent);
    		                // When you want to determine the velocity, call
    		                // computeCurrentVelocity(). Then call getXVelocity()
    		                // and getYVelocity() to retrieve the velocity for each pointer ID.
    		                mVelocityTracker.computeCurrentVelocity(1000);
    		                // Log velocity of pixels per second
    		                xVelocity = mVelocityTracker.getXVelocity(mPointerId);
    		                yVelocity = mVelocityTracker.getYVelocity(mPointerId);
    		            break;
    		            case MotionEvent.ACTION_CANCEL:
    		                // Return a VelocityTracker object back to be re-used by others.
    		                mVelocityTracker.recycle();
    		            break;
    		        }
    	            mGestureDetector.onTouchEvent(motionEvent);
    	            return true;
    	        }
    	    }
    	    
    	    class FlingDetector extends GestureDetector.SimpleOnGestureListener {
    	        
    			public FlingDetector() {
    	            super();
    	        }
    	        @Override
    	        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
    	        //    updateText("in onFling");
    	            return true;
    	        }
    	        @Override
    	        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    	        //    updateText(String.format("onScroll velocity = (%f, %f)", mTouchListener.xVelocity, mTouchListener.yVelocity));
    	        	
    	            return false;
    	        }
    	    }

    ViewConfiguration的使用主要使用了该类的下面三个方法:
    private final int TOUCH_SLOP = ViewConfiguration.get(getContext()).getScaledTouchSlop();
    configuration.getScaledTouchSlop()//获得能够进行手势滑动的距离
    configuration.getScaledMinimumFlingVelocity()//获得允许执行一个fling手势动作的最小速度值
    configuration.getScaledMaximumFlingVelocity()//获得允许执行一个fling手势动作的最大速度值


    持续更新中。。。




  • 相关阅读:
    R 包安装问题
    特征值分解与奇异值分解
    向量内积&外积
    hdu_3449(有依赖背包)
    Gene co-expression analysis for functional classification and gene–disease predictions
    MCMC & 贝叶斯
    继承(来自视频)
    面向对象 创建对象
    mongodb笔记(三)
    mongodb笔记(二)
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6818967.html
Copyright © 2020-2023  润新知