![]() | ![]() | ![]() |
사용자로 하여금 리스트에 표시된 데이터의 위치를 변경할 수 있도록 하고싶은데 편집을 사용하도록 하기에는 부담이 따른다면(혹은 숨겨진 기능으로) LongClick을 이용해서 리스트의 순서를 변경하도록 하는 방법을 생각 할 수 있다.
https://github.com/commonsguy/cwac-touchlist를 참고로 만들보았다.
TouchListView.java
public class TouchListView extends ListView {
private static final int SCROLLPOINT = 30;
private ImageView mDragView;
private WindowManager.LayoutParams mWindowParams;
private WindowManager mWindowManager;
private int currentPosition;
private int viewCenter;
private DropListener dragListener;
private RemoveListener removeListener;
private Bitmap dragBitmap;
private boolean moveMode = false;
public TouchListView(Context context) {
super(context);
init();
}
public TouchListView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TouchListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
// windowManager 를 초기화 합니다.
private void init() {
mWindowParams = new WindowManager.LayoutParams();
mWindowParams.gravity = Gravity.TOP;
mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
mWindowParams.format = PixelFormat.TRANSLUCENT;
mWindowParams.windowAnimations = 0;
mWindowManager = (WindowManager) getContext()
.getSystemService("window");
}
public void setDragListener(DropListener dragListener) {
this.dragListener = dragListener;
}
public void setRemoveListener(RemoveListener removeListener) {
this.removeListener = removeListener;
}
//이동모드인지 스크롤 모드인지를 입력받는다.
public void setMoveMode(boolean moveMode){
this.moveMode = moveMode;
}
//이동 모드를 시작한다.
public void start(int position){
if (position == AdapterView.INVALID_POSITION) {
return;
}
TextView child = (TextView) getChildAt(position - getFirstVisiblePosition());
child.setTextColor(Color.WHITE);
child.setDrawingCacheEnabled(true);
viewCenter = child.getHeight() / 2;
stopDragging();
startDragging(0, child.getHeight()/2+child.getTop(), child);
currentPosition = position;
removeListener.remove(position);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (moveMode) {
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_UP: {
stopDragging();
moveMode = false;
if (dragListener != null) {
//터치위치를 찾아 셀의 포지션을 넘긴다.
int position = pointToPosition(x, y);
if (position == AdapterView.INVALID_POSITION) {
break;
}
View currentView = getChildAt(position
- getFirstVisiblePosition());
//터치위치의 중앙을 기준으로 높으면 현위치를 작으면 아래의 인덱스를 넘긴다.
int dropPosition = (currentView.getHeight() / 2)
+ currentView.getTop() > y ? position
: position + 1;
dragListener.drop(dropPosition);
}
break;
}
case MotionEvent.ACTION_CANCEL: {
for (int i = getFirstVisiblePosition(); i
+ getFirstVisiblePosition() < getLastVisiblePosition(); i++) {
getChildAt(i - getFirstVisiblePosition()).setVisibility(
View.VISIBLE);
}
stopDragging();
moveMode = false;
}
case MotionEvent.ACTION_MOVE: {
mWindowParams.y = y + viewCenter;
if (mDragView == null) {
break;
}
mWindowManager.updateViewLayout(mDragView, mWindowParams);
int position = pointToPosition(x, y);
if (position == AdapterView.INVALID_POSITION) {
break;
}
if (position != currentPosition) {
currentPosition = position;
}
int speed = 0;
//터치위치를 기준으로 스크롤 여부와 속도를 결정한다.
if (y > getBottom() - SCROLLPOINT) {
speed = ((y - getBottom() + SCROLLPOINT) / 2);
} else if (y < getTop() + SCROLLPOINT) {
speed = ((y - getTop() - SCROLLPOINT) / 2);
}
if (speed != 0) {
int ref = pointToPosition(0, getHeight() / 2);
if (ref == AdapterView.INVALID_POSITION) {
ref = pointToPosition(0, getHeight() / 2
+ getDividerHeight());
}
View v = getChildAt(ref - getFirstVisiblePosition());
if (v != null) {
int pos = v.getTop();
setSelectionFromTop(ref, pos - speed);
}
scroll(speed);
}
}
}
return true;
}
return super.onTouchEvent(ev);
}
//속도에 맞추어 스크롤을 움직인다.
private void scroll(int speed) {
int ref = pointToPosition(0, getHeight() / 2);
if (ref == AdapterView.INVALID_POSITION) {
ref = pointToPosition(0, getHeight() / 2 + getDividerHeight());
}
View v = getChildAt(ref - getFirstVisiblePosition());
if (v != null) {
int pos = v.getTop();
setSelectionFromTop(ref, pos - speed);
}
}
private void stopDragging() {
if (dragBitmap != null) {
dragBitmap.recycle();
dragBitmap = null;
}
if (mDragView != null) {
WindowManager wm = (WindowManager) getContext().getSystemService(
"window");
wm.removeView(mDragView);
mDragView.setImageDrawable(null);
mDragView = null;
}
}
private void startDragging(int x, int y, View dragView) {
dragBitmap = Bitmap.createBitmap(dragView.getDrawingCache());
mDragView = new ImageView(getContext());
mDragView.setAlpha(190);
mDragView.setImageBitmap(dragBitmap);
mWindowParams.x = x;
mWindowParams.y = y;
mWindowManager.addView(mDragView, mWindowParams);
}
public interface DropListener {
void drop(int position);
}
public interface RemoveListener {
void remove(int which);
}
}TestActivity.java
public class TestActivity extends Activity implements DropListener,RemoveListener {
private static String[] items = { "lorem", "ipsum", "dolor", "sit", "amet",
"consectetuer", "adipiscing", "elit", "morbi", "vel", "ligula",
"vitae", "arcu", "aliquet", "mollis", "etiam", "vel", "erat",
"placerat", "ante", "porttitor", "sodales", "pellentesque",
"augue", "purus" };
private ArrayList<String> array = new ArrayList<String>(Arrays
.asList(items));
ArrayAdapter<String> aa;
TouchListView tlv;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
aa = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,array);
tlv = (TouchListView) findViewById(R.id.list);
tlv.setAdapter(aa);
tlv.setDragListener(this);
tlv.setRemoveListener(this);
tlv.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
tlv.setMoveMode(true);
tlv.start(arg2);
return true;
}
});
}
String dragData;
@Override
public void drop(int position) {
aa.insert(dragData, position);
aa.notifyDataSetChanged();
}
@Override
public void remove(int which) {
dragData = aa.getItem(which);
aa.remove(dragData);
aa.notifyDataSetChanged();
}
}


