사용자 삽입 이미지사용자 삽입 이미지사용자 삽입 이미지


사용자로 하여금 리스트에 표시된 데이터의 위치를 변경할 수 있도록 하고싶은데 편집을 사용하도록 하기에는 부담이 따른다면(혹은 숨겨진 기능으로) 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();
	}
	

}
2011/06/26 21:14 2011/06/26 21:14

trackback url: http://jeonglim.net/blog/trackback/77

1 2 3 4 5 6 7 8 9 ... 69