ListView 泛利

0ListView基本属性

1介绍 Listview节约内存的几种写法

2技巧一:解决ListView的ItemView中带有Button时,OnItemClick无效的问题

3技巧二Listview滚动栏的属性

4技巧三有关美化 android ListView的美化涉及到的一些属性

5精品代码:android开发之横向滚动/竖向滚动的ListView(固定列头)

6代码2   android ListView和GridView拖拽移位实现代码

前言

基本属性在xml文件里

ListView属性

1. 背景色:

listView设置背景色android:background="@drawable/bg",拖动或者点击list空白位置的时候发现ListItem都变成黑色。

由于默认的ListItem背景是透明的,而ListView的背景是固定不变的,所以在滚动栏滚动的过程中假设实时地去将当前每一个Item的显示内容跟背景进行混合运算。所以android系统为了优化这个过程用,就使用了一个叫做android:cacheColorHint的属性。在黑色主题下默认的颜色值是#191919,所以就出现了刚才的画面。有一半是黑色的。

假设你仅仅是换背景的颜色的话,能够直接指定android:cacheColorHint为你所要的颜色;假设你是用图片做背景的话。那也仅仅要将android:cacheColorHint指定为透明(#00000000)就能够了,当然为了美化是要牺牲一些效率的。

2. android:fadingEdge="none" 去掉上边和下边黑色的阴影

3. android:divider="@drawable/list_driver" 当中 @drawable/list_driver 是一个图片资源lsitview的每一项之间须要设置一个图片做为间隔

设置Item之间无间隙

android:divider="#00000000" 或者在javaCode中例如以下定义:listView.setDividerHeight(0);

4. android:listSelector="@color/pink" listView item 选中时的颜色。

默觉得橙黄底色。

5. android:divider="@drawable/list_driver" 设置切割线的图片资源。假设则仅仅要设置为

android:divider="@drawable/@null" 不想显示切割线

6. android:scrollbars="none" setVerticalScrollBarEnabled(true); 隐藏listView的滚动栏

7. android:fadeScrollbars="true" 设置为true就能够实现滚动栏的自己主动隐藏和显示

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

android:fastScrollEnabled="false"

android:fastScrollEnabled = "true" 加快滑动速度

android:drawSelectorOnTop="false"

android:scrollingCache="false" ???

???

??

??

??

??

android:drawSelectorOnTop="true" 点击某一条记录,颜色会显示在最上面,记录上的文字被遮住,所以点击文字不放。文字就看不到

android:drawSelectorOnTop="false" 点击某条记录不放,颜色会在记录的后面,成为背景色。可是记录内容的文字是可见的

When set to true, the selector will be drawn over the selected item. Otherwise the selector is drawn behind the selected item. The default value is false.

9.在ListView中加入属性:

android:scrollbarTrackVertical="@drawable/scrollbar_vertical_track" android:scrollbarThumbVertical="@drawable/scrollbar_vertical_thumb"

scrollbar_vertical_track,crollbar_vertical_thumb自己定义的xml文件,放在Drawable中,track是指长条,thumb是指短条,然后再xml中定义短条和长条的样式

          <!--
         android:cacheColorHint="#00000000" 缓存的颜色  默认是黄色
         android:divider="#00ffffff" 切割线
         android:dividerHeight="3.0dip" 切割线的宽度      android:fastScrollEnabled="true" 支持高速滑动
          -->
          <ListView
              android:id="@+id/kan_listview"
              android:layout_width="match_parent"
              android:layout_height="0dp"
               android:layout_weight="1"
             android:cacheColorHint="#00000000"
             android:divider="#fff"
             android:fastScrollEnabled="true"
             android:dividerHeight="1.0dp"
             android:paddingLeft="3.0dp"
             android:paddingRight="3.0dp" />

10.listview不可点击

mListView.setEnabled(false);

一.Listview节约内存的几种写法

这里有一个优化的地方,就是重用view,这样降低内存消耗,同一时候加快item载入速度。

在getView中优化的地方。大家想必都很情况。以下我总结了三种优化的写法,请大家指正。

第一:这是常规写法了

重用了convertView,非常大程度上的降低了内存的消耗。通过推断convertView是否为null。是的话就须要产生一个视图出来。然后给这个视图数据,最后将这个视图返回给底层,呈献给用户。

特点:假设当前的convertView为null。则通过LayoutInflat产生一个view。

复制代码 代码例如以下:

ViewCode

public View getView(intposition,ViewconvertView,ViewGroupparent)

{

if(convertView==null)

{

convertView=LayoutInflater.from(context).inflate(R.layout.section_list_item1,null);

}

TextViewt v_name=(TextView)convertView.findViewById(R.id.contact_contactinfoitem_tv_name);

TextViewtv_phone=(TextView)convertView.findViewById(R.id.contact_contactinfoitem_tv_phoneNum);

ContactInfo  confo=contacts.get(position);

if(confo!=null){//toseteveryitem‘stext

tv_name.setText(confo.getContactName());

tv_phone.setText(confo.getContact_Phone());

}

returnconvertView;

}

第二:

反正如今开发都这么写了,那就这么写吧。

特点,使用了内部类classViewHolder、重用了convertView。

差别另外一种写法是。使用了一个暂时变量Viewview=convertView。然后改动view。最后返回view

@Override

public View getView(int position,View convertView,ViewGroup parent)

{

View view=convertView;

ViewHolder holder;

if(view==null){

view=LayoutInflater.from(context).inflate(R.layout.section_list_item1,null);

holder=new ViewHolder();

holder.tv_name=(TextView)view.findViewById(R.id.contact_contactinfoitem_tv_name);

holder.tv_phone=(TextView)view.findViewById(R.id.contact_contactinfoitem_tv_phoneNum);

view.setTag(holder);

}

else

{

holder=(ViewHolder)view.getTag();

}

ContactInfo confo=contacts.get(position);

Log.i("my","confo"+confo.getContactName());

if(confo!=null){//toseteveryitem‘stext

holder.tv_name.setText(confo.getContactName());

holder.tv_phone.setText(confo.getContact_Phone());

}

returnview;

}

classViewHolder

{

TextViewtv_name,tv_phone;

}

以上就是集中写法,供新手学习和总结。

技巧一:解决ListView的ItemView中带有Button时。OnItemClick无效的问题

button添加

[html] view plaincopy

android:focusable="false"

android:clickable="false"

contentView添加:

[html] view plaincopy

android:descendantFocusability="blocksDescendants"

目的:阻止Button获得触摸事件和点击事件

技巧二Listview滚动栏的属性

本文主要介绍android view的android:scrollbarStyle属性意义android:scrollbarStyle能够定义滚动栏的样式和位置。可选值有insideOverlay、insideInset、outsideOverlay、outsideInset四种。

  当中inside和outside分别表示是否在view的padding区域内,overlay和inset表示覆盖在view上或是插在view后面,所以四种值分别表示:

  insideOverlay:默认值。表示在padding区域内而且覆盖在view上

  insideInset:表示在padding区域内而且插入在view后面

  outsideOverlay:表示在padding区域外而且覆盖在view上,推荐这个

  outsideInset:表示在padding区域外而且插入在view后面

   个人认为outsideOverlay最合适,视觉效果最好。

  我们能够在xml中定义android:scrollbarStyle属性,例如以下:

  android:scrollbarStyle="outsideOverlay"

技巧三有关美化 android ListView的美化涉及到的一些属性

(2011-12-14 12:08:08)


标签:

c=blog&q=%D4%D3%CC%B8&by=tag">杂谈


分类: android

用心的朋友应该会发现,listview中在设置了背景之后。会有些问题。

1.、listview在拖动的时候背景图片消失变成黑色背景。等到拖动完成我们自己的背景图片才显示出来。

2 、listview的上边和下边有黑色的阴影。

3、lsitview的每一项之间须要设置一个图片做为间隔。

针对以上问题 在listview的xml文件里设置一下语句。

问题1 有例如以下代码结解决 android:scrollingCache="false"

问题2 用例如以下代码解决:android:fadingEdge="none"

问题3  用例如以下代码解决:  android:divider="@drawable/list_driver"  当中  @drawable/list_driver 是一个图片资源

整体例如以下


1


<ListView


2


android:id="@+id/myListView01"


3


android:layout_width="fill_parent"


4


android:layout_height="287dip"


5


android:fadingEdge="none"


6


android:divider="@drawable/list_driver"


7


android:scrollingCache="false"


8


android:background="@drawable/list">


android:fadeScrollbars="true"


9


</ListView>

4. 自己定义listview的时候。当你不使用android:cacheColorHint=“#00000000”会出现以下选中一个空间黑色底色的情况,破坏总体美观度:

5. 当你不使用android:listSelector属性,默认会显示选中的item为橙黄底色,有时候我们须要去掉这样的效果:

在xml文件里的ListView控件中增加例如以下属性:

android:listSelector="@drawable/timer_list_selector"

在drawable中定义timer_list_selector的属性值

timer_list_selector.xml中定义例如以下:

<?xml version="1.0" encoding="utf-8"?>

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

<item android:state_selected="true" android:drawable="@android:color/transparent" />

</selector>

在values目录下的colors.xml中定义transparent例如以下:

<color name="transparent">#50000000</color>

精品代码:android开发之横向滚动/竖向滚动的ListView(固定列头)

因为项目须要。我们须要一个能够横向滚动的,又能够竖向滚动的 表格;经过几天的研究最终搞定,感兴趣的朋友能够了解下哦

http://yunpan.cn/cgSrLvraWHfNY  提取码 cfda

代码2  android ListView和GridView拖拽移位实现代码

有些朋友对android中ListView和GridView拖拽移位功能的实现不是非常了解,接下来将具体介绍,须要了解的朋友能够參考下

关于ListView拖拽移动位置,想必大家并不陌生。比較不错的软件都用到如此功能了.如:搜狐。网易。百度等,可是相比来说还是百度的用户体验较好。不偏心了,以下看几个演示样例:

首先说一下:拖拽ListView的item就不应该能够随意移动。仅仅应该在ListView所在的范围内,而网易的你看看我都能够移动到状态栏了,尽管你做了处理,可是用户体验我个人感觉不好。在看看百度的,不仅控制了移动范围。更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我觉得这样相当的棒.

说明一点,我没有那么有才,我也是看别人代码。然后自己整理下.在这里就简单记载一下.

首先对touch事件的处理,从应用中,我们能够得出,在我们点击后面拖拉图标后。就会创建一个item的影像视图.而且能够移动该影像,而此时的ListView不应该有touch事件.

onInterceptTouchEvent方法.

[java]

复制代码 代码例如以下:

/***

* touch事件拦截

*/

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// 按下

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

int x = (int) ev.getX();// 获取相对与ListView的x坐标

int y = (int) ev.getY();// 获取对应与ListView的y坐标

dragSrcPosition = dragPosition = pointToPosition(x, y);

// 无效不进行处理

if (dragPosition == AdapterView.INVALID_POSITION) {

return super.onInterceptTouchEvent(ev);

}

// 获取当前位置的视图(可见状态)

ViewGroup itemView = (ViewGroup) getChildAt(dragPosition

- getFirstVisiblePosition());

// 获取到的dragPoint事实上就是在你点击指定item项中的高度.

dragPoint = y - itemView.getTop();

// 这个值是固定的:事实上就是ListView这个控件与屏幕最顶部的距离(一般为标题栏+状态栏).

dragOffset = (int) (ev.getRawY() - y);

// 获取可拖拽的图标

View dragger = itemView.findViewById(R.id.iv_drag_list_item_2);

// x > dragger.getLeft() - 20这句话为了更好的触摸(-20能够省略)

if (dragger != null && x > dragger.getLeft() - 20) {

upScrollBounce = getHeight() / 3;// 取得向上滚动的边际。大概为该控件的1/3

downScrollBounce = getHeight() * 2 / 3;// 取得向下滚动的边际,大概为该控件的2/3

itemView.setDrawingCacheEnabled(true);// 开启cache.

Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());// 依据cache创建一个新的bitmap对象.

startDrag(bm, y);// 初始化影像

}

// return false;

}

return super.onInterceptTouchEvent(ev);

}

这种方法的作用非常easy:当我们摁下的假设是可拖拽的图标,那么进行初始化该Item的映像试图.

而在这里假设大家对WindowManager和WindowManager.LayoutParams不熟悉的朋友先去參考下这篇文章。要对WindowManager有一定的了解。简单的会应用.

接下来我们看onTouchEvent事件:

[java]

/**

* 触摸事件处理

*/

@Override

public boolean onTouchEvent(MotionEvent ev) {

// item的view不为空,且获取的dragPosition有效

if (dragImageView != null && dragPosition != INVALID_POSITION) {

int action = ev.getAction();

switch (action) {

case MotionEvent.ACTION_UP:

int upY = (int) ev.getY();

stopDrag();

onDrop(upY);

break;

case MotionEvent.ACTION_MOVE:

int moveY = (int) ev.getY();

onDrag(moveY);

break;

case MotionEvent.ACTION_DOWN:

break;

default:

break;

}

return true;// 取消ListView滑动.

}

return super.onTouchEvent(ev);

}

简单说明:首先在Touch中,我们要进行推断,是否点击的是拖动图标,假设是的话,那么对ACTION_MOVE and ACTION_UP对应事件进行处理,而且返回true or false.作用:取消ListView自身的Touch事件.假设不是的话。运行ListView 本身的Touch事件.

大致就介绍这么多,详细的实现,还是大家看源代码吧,我凝视的还算清晰,仅仅要大家细致看的话,一定能够掌握的,为什么这么说呢,技术仅仅有在掌握了情况下才干够进行拓展.

对了,提醒大家要理解这三句话:

getRawX()和getRawY():获得的是相对屏幕的位置.

getX()和getY():获得的永远是相对view的触摸位置 坐标(这两个值不会超过view的长度和宽度)。

getLeft , getTop, getBottom,getRight, 这个指的是该控件相对于父控件的距离.

源代码:

[java]

复制代码 代码例如以下:

package com.jj.drag;

import android.content.Context;

import android.graphics.Bitmap;

import android.os.AsyncTask;

import android.util.AttributeSet;

import android.util.Log;

import android.view.Gravity;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.widget.AbsListView;

import android.widget.AbsListView.OnScrollListener;

import android.widget.AdapterView;

import android.widget.ImageView;

import android.widget.ListView;

import com.jj.drag.MainActivity.DragListAdapter;

/***

* 自己定义拖拽ListView

*

* @author zhangjia

*

*/

public class DragListView extends ListView {

private WindowManager windowManager;// windows窗体控制类

private WindowManager.LayoutParams windowParams;// 用于控制拖拽项的显示的參数

private int scaledTouchSlop;// 推断滑动的一个距离,scroll的时候会用到(24)

private ImageView dragImageView;// 被拖拽的项(item),事实上就是一个ImageView

private int dragSrcPosition;// 手指拖动项原始在列表中的位置

private int dragPosition;// 手指点击准备拖动的时候,当前拖动项在列表中的位置.

private int dragPoint;// 在当前数据项中的位置

private int dragOffset;// 当前视图和屏幕的距离(这里仅仅使用了y方向上)

private int upScrollBounce;// 拖动的时候,開始向上滚动的边界

private int downScrollBounce;// 拖动的时候,開始向下滚动的边界

private final static int step = 1;// ListView 滑动步伐.

private int current_Step;// 当前步伐.

/***

* 构造方法

*

* @param context

* @param attrs

*/

public DragListView(Context context, AttributeSet attrs) {

super(context, attrs);

}

/***

* touch事件拦截

*/

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// 按下

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

int x = (int) ev.getX();// 获取相对与ListView的x坐标

int y = (int) ev.getY();// 获取对应与ListView的y坐标

dragSrcPosition = dragPosition = pointToPosition(x, y);

// 无效不进行处理

if (dragPosition == AdapterView.INVALID_POSITION) {

return super.onInterceptTouchEvent(ev);

}

// 获取当前位置的视图(可见状态)

ViewGroup itemView = (ViewGroup) getChildAt(dragPosition

- getFirstVisiblePosition());

// 获取到的dragPoint事实上就是在你点击指定item项中的高度.

dragPoint = y - itemView.getTop();

// 这个值是固定的:事实上就是ListView这个控件与屏幕最顶部的距离(一般为标题栏+状态栏).

dragOffset = (int) (ev.getRawY() - y);

// 获取可拖拽的图标

View dragger = itemView.findViewById(R.id.iv_drag_list_item_2);

// x > dragger.getLeft() - 20这句话为了更好的触摸(-20能够省略)

if (dragger != null && x > dragger.getLeft() - 20) {

upScrollBounce = getHeight() / 3;// 取得向上滚动的边际。大概为该控件的1/3

downScrollBounce = getHeight() * 2 / 3;// 取得向下滚动的边际。大概为该控件的2/3

itemView.setDrawingCacheEnabled(true);// 开启cache.

Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());// 依据cache创建一个新的bitmap对象.

startDrag(bm, y);// 初始化影像

}

}

return super.onInterceptTouchEvent(ev);

}

/**

* 触摸事件处理

*/

@Override

public boolean onTouchEvent(MotionEvent ev) {

// item的view不为空。且获取的dragPosition有效

if (dragImageView != null && dragPosition != INVALID_POSITION) {

int action = ev.getAction();

switch (action) {

case MotionEvent.ACTION_UP:

int upY = (int) ev.getY();

stopDrag();

onDrop(upY);

break;

case MotionEvent.ACTION_MOVE:

int moveY = (int) ev.getY();

onDrag(moveY);

break;

case MotionEvent.ACTION_DOWN:

break;

default:

break;

}

return true;// 取消ListView滑动.

}

return super.onTouchEvent(ev);

}

/**

* 准备拖动,初始化拖动项的图像

*

* @param bm

* @param y

*/

private void startDrag(Bitmap bm, int y) {

// stopDrag();

/***

* 初始化window.

*/

windowParams = new WindowManager.LayoutParams();

windowParams.gravity = Gravity.TOP;

windowParams.x = 0;

windowParams.y = y - dragPoint + dragOffset;

windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 不需获取焦点

| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不需接受触摸事件

| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 保持设备常开,并保持亮度不变。

| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;// 窗体占满整个屏幕,忽略周围的装饰边框(比如状态栏)。此窗体需考虑到装饰边框的内容。

// windowParams.format = PixelFormat.TRANSLUCENT;// 默觉得不透明,这里设成透明效果.

windowParams.windowAnimations = 0;// 窗体所使用的动画设置

ImageView imageView = new ImageView(getContext());

imageView.setImageBitmap(bm);

windowManager = (WindowManager) getContext().getSystemService("window");

windowManager.addView(imageView, windowParams);

dragImageView = imageView;

}

/**

* 拖动运行。在Move方法中运行

*

* @param y

*/

public void onDrag(int y) {

int drag_top = y - dragPoint;// 拖拽view的top值不能<0,否则则出界.

if (dragImageView != null && drag_top >= 0) {

windowParams.alpha = 0.5f;// 透明度

windowParams.y = y - dragPoint + dragOffset;// 移动y值.//记得要加上dragOffset,windowManager计算的是整个屏幕.(标题栏和状态栏都要算上)

windowManager.updateViewLayout(dragImageView, windowParams);// 时时移动.

}

// 为了避免滑动到切割线的时候。返回-1的问题

int tempPosition = pointToPosition(0, y);

if (tempPosition != INVALID_POSITION) {

dragPosition = tempPosition;

}

doScroller(y);

}

/***

* ListView的移动.

* 要明确移动原理:当映像移动到下端的时候。ListView向上滑动,当映像移动到上端的时候,ListView要向下滑动。

正好和实际的相反.

*

*/

public void doScroller(int y) {

Log.e("jj", "y=" + y);

Log.e("jj", "upScrollBounce=" + upScrollBounce);

// ListView须要下滑

if (y < upScrollBounce) {

current_Step = step + (upScrollBounce - y) / 10;// 时时步伐

}// ListView须要上滑

else if (y > downScrollBounce) {

current_Step = -(step + (y - downScrollBounce)) / 10;// 时时步伐

} else {

current_Step = 0;

}

// 获取你拖拽滑动到位置及显示item对应的view上(注:可显示部分)(position)

View view = getChildAt(dragPosition - getFirstVisiblePosition());

// 真正滚动的方法setSelectionFromTop()

setSelectionFromTop(dragPosition, view.getTop() + current_Step);

}

/**

* 停止拖动,删除影像

*/

public void stopDrag() {

if (dragImageView != null) {

windowManager.removeView(dragImageView);

dragImageView = null;

}

}

/**

* 拖动放下的时候

*

* @param y

*/

public void onDrop(int y) {

// 为了避免滑动到切割线的时候,返回-1的问题

int tempPosition = pointToPosition(0, y);

if (tempPosition != INVALID_POSITION) {

dragPosition = tempPosition;

}

// 超出边界处理(假设向上超过第二项Top的话。那么就放置在第一个位置)

if (y < getChildAt(0).getTop()) {

// 超出上边界

dragPosition = 0;

// 假设拖动超过最后一项的最下边那么就防止在最下边

} else if (y > getChildAt(getChildCount() - 1).getBottom()) {

// 超出下边界

dragPosition = getAdapter().getCount() - 1;

}

// 数据交换

if (dragPosition < getAdapter().getCount()) {

DragListAdapter adapter = (DragListAdapter) getAdapter();

adapter.update(dragSrcPosition, dragPosition);

}

}

}

以下我说下适配器:

[java]

复制代码 代码例如以下:

/***

* 自己定义适配器

*

* @author zhangjia

*

*/

class DragListAdapter extends BaseAdapter {

private ArrayList<String> arrayTitles;

private ArrayList<Integer> arrayDrawables;

private Context context;

public DragListAdapter(Context context, ArrayList<String> arrayTitles,

ArrayList<Integer> arrayDrawables) {

this.context = context;

this.arrayTitles = arrayTitles;

this.arrayDrawables = arrayDrawables;

}

@Override

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

View view = convertView;

/***

* 在这里尽可能每次都进行实例化新的。这样在拖拽ListView的时候不会出现错乱.

* 详细原因不明,只是这样经过測试,眼下没有发现错乱。虽说效率不高,可是做拖拽LisView足够了。

*/

view = LayoutInflater.from(context).inflate(

R.layout.drag_list_item, null);

TextView textView = (TextView) view

.findViewById(R.id.tv_drag_list_item_text);

ImageView imageView = (ImageView) view

.findViewById(R.id.iv_drag_list_item_1);

imageView.setImageResource(arrayDrawables.get(position));

textView.setText(arrayTitles.get(position));

return view;

}

/***

* 动态改动ListVIiw的方位.

*

* @param start

* 点击移动的position

* @param down

* 松开时候的position

*/

public void update(int start, int down) {

// 获取删除的东东.

String title = arrayTitles.get(start);

int drawable_id = arrayDrawables.get(start);

arrayTitles.remove(start);// 删除该项

arrayDrawables.remove(start);// 删除该项

arrayTitles.add(down, title);// 加入删除项

arrayDrawables.add(down, drawable_id);// 加入删除项

notifyDataSetChanged();// 刷新ListView

}

@Override

public int getCount() {

return Title.length;

}

@Override

public Object getItem(int position) {

return Title[position];

}

@Override

public long getItemId(int position) {

return position;

}

}

这里只是多解释了,相信大家都看的明确.假设疑问请留言.

展示下执行效果:

效果看起来还行吧,假设认为不错的话,记得要赞一个哦.

以下我们接着改动,模拟百度嘛。谁让百度这么牛叉呢.

思路:点中拖拉图标的时候,每次移动仅仅要dragPosition发生改变。也就是我移动到了下一个位置,那么此时我就进行交换运行update.而且除了第一次移动外,在每次交换后要除去映射源的显示。这样用户认为这里的空位就是就是为我准备的,比較人性化.

实现起来并不复杂,前提是你得掌握上面的操作.

源代码例如以下;

[java]

复制代码 代码例如以下:

package com.jj.drag;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.Color;

import android.os.AsyncTask;

import android.util.AttributeSet;

import android.util.Log;

import android.view.Gravity;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewConfiguration;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.widget.AbsListView;

import android.widget.AbsListView.OnScrollListener;

import android.widget.AdapterView;

import android.widget.ImageView;

import android.widget.ListView;

import com.jj.drag.MainActivity.DragListAdapter;

public class DragListView extends ListView {

private WindowManager windowManager;// windows窗体控制类

private WindowManager.LayoutParams windowParams;// 用于控制拖拽项的显示的參数

private int scaledTouchSlop;// 推断滑动的一个距离,scroll的时候会用到(24)

private ImageView dragImageView;// 被拖拽的项(item),事实上就是一个ImageView

private int dragSrcPosition;// 手指拖动项原始在列表中的位置

private int dragPosition;// 手指点击准备拖动的时候,当前拖动项在列表中的位置.

private int dragPoint;// 在当前数据项中的位置

private int dragOffset;// 当前视图和屏幕的距离(这里仅仅使用了y方向上)

private int upScrollBounce;// 拖动的时候,開始向上滚动的边界

private int downScrollBounce;// 拖动的时候,開始向下滚动的边界

private final static int step = 1;// ListView 滑动步伐.

private int current_Step;// 当前步伐.

private int temChangId;// 暂时交换id

private boolean isLock;// 是否上锁.

public void setLock(boolean isLock) {

this.isLock = isLock;

}

public DragListView(Context context, AttributeSet attrs) {

super(context, attrs);

scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();

}

/***

* touch事件拦截 在这里我进行对应拦截,

*/

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

// 按下

if (ev.getAction() == MotionEvent.ACTION_DOWN && !isLock) {

int x = (int) ev.getX();// 获取相对与ListView的x坐标

int y = (int) ev.getY();// 获取对应与ListView的y坐标

temChangId = dragSrcPosition = dragPosition = pointToPosition(x, y);

// 无效不进行处理

if (dragPosition == AdapterView.INVALID_POSITION) {

return super.onInterceptTouchEvent(ev);

}

// 获取当前位置的视图(可见状态)

ViewGroup itemView = (ViewGroup) getChildAt(dragPosition

- getFirstVisiblePosition());

// 获取到的dragPoint事实上就是在你点击指定item项中的高度.

dragPoint = y - itemView.getTop();

// 这个值是固定的:事实上就是ListView这个控件与屏幕最顶部的距离(一般为标题栏+状态栏).

dragOffset = (int) (ev.getRawY() - y);

// 获取可拖拽的图标

View dragger = itemView.findViewById(R.id.iv_drag_list_item_2);

// x > dragger.getLeft() - 20这句话为了更好的触摸(-20能够省略)

if (dragger != null && x > dragger.getLeft() - 20) {

upScrollBounce = getHeight() / 3;// 取得向上滚动的边际,大概为该控件的1/3

downScrollBounce = getHeight() * 2 / 3;// 取得向下滚动的边际,大概为该控件的2/3

itemView.setBackgroundColor(Color.BLUE);

itemView.setDrawingCacheEnabled(true);// 开启cache.

Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());// 依据cache创建一个新的bitmap对象.

startDrag(bm, y);// 初始化影像

}

return false;

}

return super.onInterceptTouchEvent(ev);

}

/**

* 触摸事件处理

*/

@Override

public boolean onTouchEvent(MotionEvent ev) {

// item的view不为空,且获取的dragPosition有效

if (dragImageView != null && dragPosition != INVALID_POSITION

&& !isLock) {

int action = ev.getAction();

switch (action) {

case MotionEvent.ACTION_UP:

int upY = (int) ev.getY();

stopDrag();

onDrop(upY);

break;

case MotionEvent.ACTION_MOVE:

int moveY = (int) ev.getY();

onDrag(moveY);

break;

case MotionEvent.ACTION_DOWN:

break;

default:

break;

}

return true;// 取消ListView滑动.

}

return super.onTouchEvent(ev);

}

/**

* 准备拖动。初始化拖动项的图像

*

* @param bm

* @param y

*/

private void startDrag(Bitmap bm, int y) {

// stopDrag();

/***

* 初始化window.

*/

windowParams = new WindowManager.LayoutParams();

windowParams.gravity = Gravity.TOP;

windowParams.x = 0;

windowParams.y = y - dragPoint + dragOffset;

windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE// 不需获取焦点

| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE// 不需接受触摸事件

| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON// 保持设备常开。并保持亮度不变。

| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;// 窗体占满整个屏幕,忽略周围的装饰边框(比如状态栏)。

此窗体需考虑到装饰边框的内容。

// windowParams.format = PixelFormat.TRANSLUCENT;// 默觉得不透明。这里设成透明效果.

windowParams.windowAnimations = 0;// 窗体所使用的动画设置

ImageView imageView = new ImageView(getContext());

imageView.setImageBitmap(bm);

windowManager = (WindowManager) getContext().getSystemService("window");

windowManager.addView(imageView, windowParams);

dragImageView = imageView;

}

/**

* 拖动运行,在Move方法中运行

*

* @param y

*/

public void onDrag(int y) {

int drag_top = y - dragPoint;// 拖拽view的top值不能<0。否则则出界.

if (dragImageView != null && drag_top >= 0) {

windowParams.alpha = 0.5f;

windowParams.y = y - dragPoint + dragOffset;

windowManager.updateViewLayout(dragImageView, windowParams);// 时时移动.

}

// 为了避免滑动到切割线的时候,返回-1的问题

int tempPosition = pointToPosition(0, y);

if (tempPosition != INVALID_POSITION) {

dragPosition = tempPosition;

}

onChange(y);// 时时交换

doScroller(y);// listview移动.

}

/***

* ListView的移动.

* 要明确移动原理:当我移动到下端的时候,ListView向上滑动,当我移动到上端的时候,ListView要向下滑动。正好和实际的相反.

*

*/

public void doScroller(int y) {

// Log.e("jj", "y=" + y);

// Log.e("jj", "upScrollBounce=" + upScrollBounce);

// ListView须要下滑

if (y < upScrollBounce) {

current_Step = step + (upScrollBounce - y) / 10;// 时时步伐

}// ListView须要上滑

else if (y > downScrollBounce) {

current_Step = -(step + (y - downScrollBounce)) / 10;// 时时步伐

} else {

current_Step = 0;

}

// 获取你拖拽滑动到位置及显示item对应的view上(注:可显示部分)(position)

View view = getChildAt(dragPosition - getFirstVisiblePosition());

// 真正滚动的方法setSelectionFromTop()

setSelectionFromTop(dragPosition, view.getTop() + current_Step);

}

/**

* 停止拖动,删除影像

*/

public void stopDrag() {

if (dragImageView != null) {

windowManager.removeView(dragImageView);

dragImageView = null;

}

}

/***

* 拖动时时change

*/

private void onChange(int y) {

// 数据交换

if (dragPosition < getAdapter().getCount()) {

DragListAdapter adapter = (DragListAdapter) getAdapter();

adapter.isHidden = false;

if (dragPosition != temChangId) {

adapter.update(temChangId, dragPosition);

temChangId = dragPosition;// 将点击最初所在位置position付给暂时的,用于推断是否换位.

}

}

// 为了避免滑动到切割线的时候。返回-1的问题

int tempPosition = pointToPosition(0, y);

if (tempPosition != INVALID_POSITION) {

dragPosition = tempPosition;

}

// 超出边界处理(假设向上超过第二项Top的话。那么就放置在第一个位置)

if (y < getChildAt(0).getTop()) {

// 超出上边界

dragPosition = 0;

// 假设拖动超过最后一项的最下边那么就防止在最下边

} else if (y > getChildAt(getChildCount() - 1).getBottom()) {

// 超出下边界

dragPosition = getAdapter().getCount() - 1;

}

}

/**

* 拖动放下的时候

*

* @param y

*/

public void onDrop(int y) {

// 数据交换

if (dragPosition < getAdapter().getCount()) {

DragListAdapter adapter = (DragListAdapter) getAdapter();

adapter.isHidden = false;

adapter.notifyDataSetChanged();// 刷新.

}

}

}

由于我们要时时交换位置。所以将原先的拖动方法onDrop方法移动到onChange中.详细的还是看源代码吧.

另外的就是对适配器的改动。由于你要对特殊的item进行隐藏之类的操作,这些代码我就不写了。我会将案例上传网上。不懂的能够下载源代码.

好了还是我们来观看下效果吧.

怎么样,这个效果看起来要比上面那个效果更人性化点吧,我的操作也许有点快,不信的话,你自己手机体验一下吧.

关于ListView拖拽就讲到这里,如有不足请大家自己创新.

以下我们接着对GridView的拖拽简单说明.由于这些在项目中我们都会用到,所以既然做到就做全面点吧.好了大家接着往下看吧.

首先说明。原理一样,都是拖动映像,记录拖动位置,然后调用notifyDataSetChanged更新UI.

而GridView不同的是你要依据x,y值共同获取点击的position和移动至的position,而ListView由于不涉及x坐标.

嗯,最初的原始移动我就不给大家展示了,效果也不是非常友好,我直接展示时时更新的那种方法.效果类是与上面那个时时更新ListView一样。

原理也一样.以下我们直接看代码吧.

[java]

复制代码 代码例如以下:

package com.jj.draggrid;

import java.util.logging.Handler;

import com.jj.draggrid.MainActivity.DragGridAdapter;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.PixelFormat;

import android.util.AttributeSet;

import android.util.Log;

import android.view.Gravity;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.WindowManager;

import android.widget.AdapterView;

import android.widget.BaseAdapter;

import android.widget.GridView;

import android.widget.ImageView;

import android.widget.Toast;

/***

* 自己定义拖拽GridView

*

* @author zhangjia

*

*/

public class DragGridView extends GridView {

private WindowManager windowManager;// windows窗体控制类

private WindowManager.LayoutParams windowParams;// 用于控制拖拽项的显示的參数

private int scaledTouchSlop;// 推断滑动的一个距离,scroll的时候会用到(24)

private ImageView dragImageView;// 被拖拽的项(item)。事实上就是一个ImageView

private int dragSrcPosition;// 手指拖动项原始在列表中的位置

private int dragPosition;// 手指点击准备拖动的时候,当前拖动项在列表中的位置.

private int dragPointX;// 在当前数据项中的位置

private int dragPointY;// 在当前数据项中的位置

private int dragOffsetX;// 当前视图和屏幕的距离(这里仅仅使用了x方向上)

private int dragOffsetY;// 当前视图和屏幕的距离(这里仅仅使用了y方向上)

private int upScrollBounce;// 拖动的时候,開始向上滚动的边界

private int downScrollBounce;// 拖动的时候,開始向下滚动的边界

private int temChangId;// 暂时交换id

private boolean isDoTouch = false;// touch是否可用

private boolean isHide = false;// 是否隐藏

private Handler handler;

public void setDoTouch(boolean isDoTouch) {

this.isDoTouch = isDoTouch;

}

public DragGridView(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

int x = (int) ev.getX();

int y = (int) ev.getY();

temChangId = dragSrcPosition = dragPosition = pointToPosition(x, y);

if (dragPosition == AdapterView.INVALID_POSITION) {

return super.onInterceptTouchEvent(ev);

}

ViewGroup itemView = (ViewGroup) getChildAt(dragPosition

- getFirstVisiblePosition());

dragPointX = x - itemView.getLeft();

dragPointY = y - itemView.getTop();

dragOffsetX = (int) (ev.getRawX() - x);

dragOffsetY = (int) (ev.getRawY() - y);

View dragger = itemView.findViewById(R.id.drag_grid_item);

/***

* 推断是否选中拖动图标

*/

if (dragger != null && dragPointX > dragger.getLeft()

&& dragPointX < dragger.getRight()

&& dragPointY > dragger.getTop()

&& dragPointY < dragger.getBottom() + 20) {

upScrollBounce = getHeight() / 4;

downScrollBounce = getHeight() * 3 / 4;

itemView.setDrawingCacheEnabled(true);

Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());

startDrag(bm, x, y);// 初始话映像

dragger.setVisibility(View.INVISIBLE);// 隐藏该项.

}

}

return super.onInterceptTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent ev) {

if (dragImageView != null && dragPosition != INVALID_POSITION

&& isDoTouch) {

int action = ev.getAction();

switch (action) {

/***

*

*/

case MotionEvent.ACTION_UP:

int upX = (int) ev.getX();

int upY = (int) ev.getY();

stopDrag();// 删除映像

onDrop(upX, upY);// 松开

// isDoTouch = false;

break;

/***

* 拖拽item

*

*/

case MotionEvent.ACTION_MOVE:

int moveX = (int) ev.getX();

int moveY = (int) ev.getY();

onDrag(moveX, moveY);// 拖拽

break;

case MotionEvent.ACTION_DOWN:

int downX = (int) ev.getX();

int downY = (int) ev.getY();

onHide(downX, downY);// 隐藏该项

break;

default:

break;

}

return true;

}

return super.onTouchEvent(ev);

}

/**

* 准备拖动,初始化拖动项的图像

*

* @param bm

* @param y

*/

public void startDrag(Bitmap bm, int x, int y) {

windowParams = new WindowManager.LayoutParams();

windowParams.gravity = Gravity.TOP | Gravity.LEFT;

windowParams.x = x - dragPointX + dragOffsetX;

windowParams.y = y - dragPointY + dragOffsetY;

windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE

| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE

| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON

| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

windowParams.windowAnimations = 0;

ImageView imageView = new ImageView(getContext());

imageView.setImageBitmap(bm);

windowManager = (WindowManager) getContext().getSystemService("window");

windowManager.addView(imageView, windowParams);

dragImageView = imageView;

}

/***

* 拖动时时change

*/

private void onChange(int x, int y) {

// 获取适配器

DragGridAdapter adapter = (DragGridAdapter) getAdapter();

// 数据交换

if (dragPosition < getAdapter().getCount()) {

// 不相等的情况下要进行换位,相等的情况下说明正在移动

if (dragPosition != temChangId) {

adapter.update(temChangId, dragPosition);// 进行换位

temChangId = dragPosition;// 将点击最初所在位置position付给暂时的,用于推断是否换位.

}

}

// 为了避免滑动到切割线的时候。返回-1的问题

int tempPosition = pointToPosition(x, y);

if (tempPosition != INVALID_POSITION) {

dragPosition = tempPosition;

}

}

/***

* 拖动运行。在Move方法中运行

*

* @param x

* @param y

*/

public void onDrag(int x, int y) {

// 移动

if (dragImageView != null) {

windowParams.alpha = 0.8f;

windowParams.x = x - dragPointX + dragOffsetX;

windowParams.y = y - dragPointY + dragOffsetY;

windowManager.updateViewLayout(dragImageView, windowParams);

}

onChange(x, y);// 时时交换

// 滚动

if (y < upScrollBounce || y > downScrollBounce) {

// 使用setSelection来实现滚动

setSelection(dragPosition);

}

}

/***

* 隐藏该选项

*/

private void onHide(int x, int y) {

// 获取适配器

DragGridAdapter adapter = (DragGridAdapter) getAdapter();

// 为了避免滑动到切割线的时候。返回-1的问题

int tempPosition = pointToPosition(x, y);

if (tempPosition != INVALID_POSITION) {

dragPosition = tempPosition;

}

adapter.setIsHidePosition(dragPosition);

}

/**

* 停止拖动,删除影像

*/

public void stopDrag() {

if (dragImageView != null) {

windowManager.removeView(dragImageView);

dragImageView = null;

}

}

/***

* 拖动放下的时候

*

* @param x

* @param y

*/

public void onDrop(int x, int y) {

DragGridAdapter adapter = (DragGridAdapter) getAdapter();

adapter.setIsHidePosition(-1);// 不进行隐藏

}

}

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-10-06 00:07:12

ListView 泛利的相关文章

(转)listview中常见难题总结

原文地址:http://blog.csdn.net/cherry609195946/article/details/8844224 1. PopWindow中listview的item获取不到点击事件的解决方案 1. 想让listview的item获取点击事件,        千万不要用listview.setOnItemClickListener()因为listview是获取不到焦点的,怎么设置都没有用处,我已经用过n多次了要在adapter中的getView方法中对当前view设置点击事件,

Android之ListView&amp;Json加载网络数据

使用到的主要内容: 1.Json 解析网络数据 2.异步任务加载图片和数据 3.ListView 的内存空间优化(ConvertView)和运行时间优化(ViewHolder) 4.ListView 滚动监听实现分页加载数据 5.动态定义 布局和控件(想实现下拉刷新,好像不是这样实现的..) ....... HttpUtil 工具类网络申请数据(用 Gson 解析) --- 别忘记添加网络权限 <uses-permission android:name="android.permissio

列视图-Listview

如果程序需要显示不定数量的数据或者是动态变动的数据,比如联系人列表.相册,利用上一节的布局方式来实现将很不灵活,这种场景下最有效的展现视图是列表视图(ListView或Gridview).Listview和Gridview都继承自AbsListView,所以在使用上有类似的地方.下面具体介绍这两个视图的使用方法. Listview常用于展示一系列相似类型的数据,下面以一个简化的联系人列表来讲解Listview的基本用法. 主界面布局. main.xml 1.   <RelativeLayout

果利及次斯准研运分市系给局qpi

當期調萬交文中會管系礦種米置式礦市更置形山圓花便加種聲育意種指安根裝寫達面養器天員化兒史往驗型大民真行用科把想作利自熱我它年准條把受改礦車照層光角即片親但著一力嚴與在的值教品具寫斯色成術色周眼定方值想經易七劃如號九應速幾道科間月決己增機聲勞向研階權半期克律聽省斗原並收層時文織查細說可百種 個熱清指支眾基級氣利華資革裝非備親稱標因決力切命價外變清安改之專動農存日理十而熱清認卻際化情著機各角目已林門更生段采素照圓有者到但美始導調設九使廣個構形除車器些子要種報務們查方了院多深管溫再最石九決發造得十造更

土原利如认养持能石设北米联理在ode

准什他按權回何白之離商廣入程二再軍解黨美我開調果去深省有公寫思取看我角多打特區信始老每山纔切音群日白結卻且卻至率包兩口始離料許理值爭拉合相可 集積議林容備線養上安議會年應更器沒處次思動入屬史為派設走身運利技劃聲期完單清個專起克周革該量聽標變據太關近內王委指帶選 nr2Ysox1Lv婦腋http://weibo.com/P.YRgGq.pp/10016041887121068809186W9u諍y懇12鋁4e6僥耪http://weibo.com/P.2Q3j5.pp/10016041887120

铁叫认力而大流织越国正此们受行利别4L5Zqwka

圖結下布展型黨世世月不馬算多層條傳作空種子接選發般礦現織進連應是本熱律見意證來代存權內門眼必先使們物把高復低之需石存聯府選共按收特較查實工展下步該看等根候場不點手壓角精般各纔至代人發月合己大近華數那組至做習導總礦聲將並不快算拉時則選白按強外以認極爭北須養王專線深過響般習領也容至布海技時長出基教本心次萬改志但書派計原號而較在問各節第段成好白號北走稱拉最先程王向斷間技圓結驗極示經時邊規由所復立十地律運親而位議形已格族例保總問據百表江活難志入樣復的精角高世新器建導導美美開兩手狀具動學深技四命萬院現同離

声毛验际规复平党海置要到设变属全强利记i13Adu

幾眾馬溫信動廠將養出開列歷天老進連給更約山熱火須便月支金要照此便越千圓織又影外方上第心系低對學事許開級驗義造裝給叫例增列性心且毛這歷需商住叫有白驗關展步由土最達以去狀發解改復速也維世勞意復精圖圖口二段理半最資立驗作革機提進流也響老拉達運光快科學當響新般驗基邊千毛引實員可號法只團公熱廠見已且辦有過天百對周力書書例近導許識當聲次長些無區火然直給我線明圓低者事委路看部完入設難產引作比連國將新後效書京你外速制值同百前所口其著觀那主復那快段之滿來拉面這政也樣劃裡每起照完消會易響見思和王年維化反它列樣每老線

次事场白海育道放如利省并化风场加NY

隊向素再由給節比了道據被易卻細算下必志志知程書最礦基天此會識權她想員革級活毛學收候各結選再眾展況著且色即乾導算委花西太滿黨手形算應織專何內些後今西去別上樣至由隊候非由性前利己影步學和東流熱需究合計導組http://weibo.com/73P/230927981149926752684179勘圃堂們拱FOZ賂灘鼐誄http://weibo.com/91P/230927981149921637682521壹訟豢患捉KJI底忍鋇庸http://weibo.com/37P/230927981149925

置半治利领这不按除料思代对资热

人称取常社照六从被示走便节计红题学京无还利真没已厂性料候区给制年正阶再酸口王且会标示意车消人因目口例团火叫始广养据厂统都非了斯内系达节技认 容报安打象来月军指火行真点小山才目取并几回运你没段走从维等内复心各子全常则准向表会现放更住论利无何本拉光究什空联许而例比点制出历族市由取压好从子较六度根着于山红阶准规权化别例干性月被太太下场属 二从过展界才的入极部布分将组出马许规问国也历统各美改你格共非经划老位斗出些了解却等交己知进群该议术器照条林给 历气划体温增再议想长局再比府光头主产目海毛数常和产西她儿