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);// 不进行隐藏

}

}

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

ListView 泛利的更多相关文章

  1. ios取证

    摘录自:<IOS取证实战> Andrew Hoog著 viaForensics公司,今年已经募集到1600万创业基金 2007-2011年初,AT&T是在美国唯一为iphone提供 ...

  2. HTML、CSS选择题

    Java EE软件工程师认证考试 试题库-选择题   一.    选择题(包括单选和双选) 1.D 以下(    )是HTML常用的块状标签(选择一项) A. <span> B. < ...

  3. (转)listview中常见难题总结

    原文地址:http://blog.csdn.net/cherry609195946/article/details/8844224 1. PopWindow中listview的item获取不到点击事件 ...

  4. Android 实现ListView中Item被单击后背景色保持高亮

    今天为了解决一个需求,就是我有一个slidingDrawer,里面是一个ListView.然后,单击其中的Item,默认只是显示一个橙色背景后就恢复了.客户便有着个需求,需要单击这个Item的背景高亮 ...

  5. React Native的组件ListView

    React Native的组件ListView类似于iOS中的UITableView和UICollectionView,也就是说React Native的组件ListView既可以实现UITableV ...

  6. (转载) listview实现微信朋友圈嵌套

    listview实现微信朋友圈嵌套 标签: androidlistview 2016-01-06 00:05 572人阅读 评论(0) 收藏 举报  分类: android(8)  版权声明:本文为博 ...

  7. Android 自定义组件,自定义LinearLayout,ListView等样式的组件

    今天讲的其实以前自己用过,就是在网上拿下来的把图片裁剪成圆形的方法,之前的随笔也介绍过的, 用法就是,在布局里写控件或者组件的时候得把从com开始到你写的那个类的所有路径写下来. 至于我们该怎么创建呢 ...

  8. 张高兴的 UWP 开发笔记:横向 ListView

    ListView 默认的排列方向是纵向 ( Orientation="Vertical" ) ,但如果我们需要横向显示的 ListView 怎么办? Blend for Visua ...

  9. Android—万能ListView适配器

    ListView是开发中最常用的控件了,但是总是会写重复的代码,浪费时间又没有意义. 最近参考一些资料,发现一个万能ListView适配器,代码量少,节省时间,总结一下分享给大家. 首先有一个自定义的 ...

随机推荐

  1. UWP 新手教程1——UWP的前世今生

    文件夹 引言 设备族群 UI 和通用输入模式 通用控件和布局面板 工具 自适应扩展 通用输入处理 引言 在本篇文章中,可以掌握下面知识: 设备族群,怎样决定目标设备 新的UI控件和新面板帮助你适应不同 ...

  2. matlab无法使用

    mathlab前一段时间使用不了,网上找到了一些出来方法. (1)修改本地时间,将本地时间改都较前的时间,就可以了, (2)使用网上的一个文件,将自己的文件替换掉就可以了 文件放在我的百度云盘里面ht ...

  3. 硬件——STM32 , 录音

    战舰V3的录音程序解析 上一章,我们实现了一个简单的音乐播放器,本章我们将在上一章的基础上,实现一个简单的录音机,实现WAV录音.本章分为如下几个部: 50.1 WAV简介 50.2 硬件设计 50. ...

  4. 一次性能优化将filter转换

    有一条SQL性能有问题,在运行计划中发现filter.遇到它要小心了,类似于nestloop.我曾经的blog对它有研究探索运行计划中filter的原理.用exists极易引起filter. 优化前: ...

  5. HIVE快速入门 分类: B4_HIVE 2015-06-06 11:27 59人阅读 评论(0) 收藏

    (一)简单入门 1.创建一个表 create table if not exists ljh_emp( name string, salary float, gender string) commen ...

  6. 【Codeforces Round #439 (Div. 2) C】The Intriguing Obsession

    [链接] 链接 [题意] 给你3种颜色的点. 每种颜色分别a,b,c个. 现在让你在这些点之间加边. 使得,同种颜色的点之间,要么不连通,要么连通,且最短路至少为3 边是无向边. 让你输出方案数 [题 ...

  7. nslookup详解(name server lookup)( 域名查询)

    nslookup详解(name server lookup)( 域名查询) 一.总结 1.爬虫倒是很方便拿到页面数据:a.网页的页面源码我们可以轻松获得  b.比如cnsd博客,文章的正文内容全部放在 ...

  8. python高级学习目录

    1. Linux介绍.命令1.1. 操作系统(科普章节) 1.2. 操作系统的发展史(科普章节) 1.3. 文件和目录 1.4. Ubuntu 图形界面入门 1.5. Linux 命令的基本使用 1. ...

  9. vuejs及相关工具介绍

    轻量级前端mvm的框架 图片.png 对es6语法的简单描述 图片.png 融合了react和angular的优点,组件化和灵活应用和指令,在国际上是一款极有潜力的前端框架. 1.双向绑定 两段相加得 ...

  10. 重拾c语言之动态内存分配

    动态内存分配 传统数组的缺点: 1数组长度必须事先制定,且仅仅能是长整数不能是变量 2传统形式定义的数组该数组的内存程序无法手动释放 3数组一旦定义,系统就会为该数组分配的存储空间就会一直存在直到该函 ...