기본 콘텐츠로 건너뛰기

안드로이드 Drag and Drop

아래내용을 사용한 예제가 있는곳:
http://blog.naver.com/PostView.nhn?blogId=monk773&logNo=90145409278

출처:http://codingdojo.kr/scode/322
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.pyframe.tools.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
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.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;

import com.mytodo.andriod.R;

public class DndListView extends ListView {

    private Context mContext;
    private ImageView mDragView;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mWindowParams;
    private int mDragPos;      // which item is being dragged
    private int mFirstDragPos; // where was the dragged item originally
    private int mDragPoint;    // at what offset inside the item did the user grab it
    private int mCoordOffset;  // the difference between screen coordinates and coordinates in this view
    private DragListener mDragListener;
    private DropListener mDropListener;
//    private RemoveListener mRemoveListener;
    private int mUpperBound;
    private int mLowerBound;
    private int mHeight;
    private GestureDetector mGestureDetector;
//    private static final int FLING = 0;
//    private static final int SLIDE = 1;
//    private int mRemoveMode = -1;
    private Rect mTempRect = new Rect();
    private Bitmap mDragBitmap;
    private final int mTouchSlop;
    private int mItemHeightNormal;
    private int mItemHeightExpanded;

    public DndListView(Context context, AttributeSet attrs) {
        super(context, attrs);
//        SharedPreferences pref = context.getSharedPreferences("Music", 3);
//        mRemoveMode = pref.getInt("deletemode", -1);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mContext = context;
//        Resources res = getResources();
//        mItemHeightNormal = res.getDimensionPixelSize(R.dimen.normal_height);
//        mItemHeightExpanded = res.getDimensionPixelSize(R.dimen.expanded_height);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mDragListener != null || mDropListener != null) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    int x = (int) ev.getX();
                    int y = (int) ev.getY();
                    int itemnum = pointToPosition(x, y);
                    if (itemnum == AdapterView.INVALID_POSITION) {
                        break;
                    }
                    ViewGroup item = (ViewGroup) getChildAt(itemnum - getFirstVisiblePosition());
                    mDragPoint = y - item.getTop();
                    mCoordOffset = ((int)ev.getRawY()) - y;
                    View dragger = item.findViewById(R.id.dragicon);

//                    item.setBackgroundColor(Color.RED);

                    Rect r = mTempRect;
                    dragger.getDrawingRect(r);
                    // The dragger icon itself is quite small, so pretend the touch area is bigger
                    if (x < r.right * 2) {
                        item.setDrawingCacheEnabled(true);
                        // Create a copy of the drawing cache so that it does not get recycled
                        // by the framework when the list tries to clean up memory
                        Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());
                        startDragging(bitmap, y);
                        mDragPos = itemnum;
                        mFirstDragPos = mDragPos;
                        mHeight = getHeight();
                        int touchSlop = mTouchSlop;
                        mUpperBound = Math.min(y - touchSlop, mHeight / 3);
                        mLowerBound = Math.max(y + touchSlop, mHeight * 2 /3);
                        return false;
                    }
                    mDragView = null;
                    break;
            }
        }
        return super.onInterceptTouchEvent(ev);
    }

    /*
     * pointToPosition() doesn't consider invisible views, but we
     * need to, so implement a slightly different version.
     */
    private int myPointToPosition(int x, int y) {
        Rect frame = mTempRect;
        final int count = getChildCount();
        for (int i = count - 1; i >= 0; i--) {
            final View child = getChildAt(i);
            child.getHitRect(frame);
            if (frame.contains(x, y)) {
                return getFirstVisiblePosition() + i;
            }
        }
        return INVALID_POSITION;
    }

    private int getItemForPosition(int y) {
        int adjustedy = y - mDragPoint - 32;
        int pos = myPointToPosition(0, adjustedy);
        if (pos >= 0) {
            if (pos <= mFirstDragPos) {
                pos += 1;
            }
        } else if (adjustedy < 0) {
            pos = 0;
        }
        return pos;
    }

    private void adjustScrollBounds(int y) {
        if (y >= mHeight / 3) {
            mUpperBound = mHeight / 3;
        }
        if (y <= mHeight * 2 / 3) {
            mLowerBound = mHeight * 2 / 3;
        }
    }

    /*
     * Restore size and visibility for all listitems
     */
    private void unExpandViews(boolean deletion) {
        for (int i = 0;; i++) {
            View v = getChildAt(i);
            if (v == null) {
                if (deletion) {
                    // HACK force update of mItemCount
                    int position = getFirstVisiblePosition();
                    int y = getChildAt(0).getTop();
                    setAdapter(getAdapter());
                    setSelectionFromTop(position, y);
                    // end hack
                }
                layoutChildren(); // force children to be recreated where needed
                v = getChildAt(i);
                if (v == null) {
                    break;
                }
            }
            ViewGroup.LayoutParams params = v.getLayoutParams();
            params.height = mItemHeightNormal;
            v.setLayoutParams(params);
            v.setVisibility(View.VISIBLE);
        }
    }

    /* Adjust visibility and size to make it appear as though
     * an item is being dragged around and other items are making
     * room for it:
     * If dropping the item would result in it still being in the
     * same place, then make the dragged listitem's size normal,
     * but make the item invisible.
     * Otherwise, if the dragged listitem is still on screen, make
     * it as small as possible and expand the item below the insert
     * point.
     * If the dragged item is not on screen, only expand the item
     * below the current insertpoint.
     */
    private void doExpansion() {
        int childnum = mDragPos - getFirstVisiblePosition();
        if (mDragPos > mFirstDragPos) {
            childnum++;
        }

        View first = getChildAt(mFirstDragPos - getFirstVisiblePosition());

        for (int i = 0;; i++) {
            View vv = getChildAt(i);
            if (vv == null) {
                break;
            }
            int height = mItemHeightNormal;
            int visibility = View.VISIBLE;
            if (vv.equals(first)) {
                // processing the item that is being dragged
                if (mDragPos == mFirstDragPos) {
                    // hovering over the original location
                    visibility = View.INVISIBLE;
                } else {
                    // not hovering over it
                    height = 1;
                }
            } else if (i == childnum) {
                if (mDragPos < getCount() - 1) {
                    height = mItemHeightExpanded;
                }
            }
            ViewGroup.LayoutParams params = vv.getLayoutParams();
            params.height = height;
            vv.setLayoutParams(params);
            vv.setVisibility(visibility);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mGestureDetector != null) {
            mGestureDetector.onTouchEvent(ev);
        }
        if ((mDragListener != null || mDropListener != null) && mDragView != null) {
            int action = ev.getAction(); 
            switch (action) {
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    Rect r = mTempRect;
                    mDragView.getDrawingRect(r);
                    stopDragging();
//                    if (mRemoveMode == SLIDE && ev.getX() > r.right * 3 / 4) {
//                        if (mRemoveListener != null) {
//                            mRemoveListener.remove(mFirstDragPos);
//                        }
//                        unExpandViews(true);
//                    } else {
                    if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount()) {
                        mDropListener.drop(mFirstDragPos, mDragPos);
                    }
                    unExpandViews(false);
//                    }
                    break;

                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    int x = (int) ev.getX();
                    int y = (int) ev.getY();
                    dragView(x, y);
                    int itemnum = getItemForPosition(y);
                    if (itemnum >= 0) {
                        if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {
                            if (mDragListener != null) {
                                mDragListener.drag(mDragPos, itemnum);
                            }
                            mDragPos = itemnum;
                            doExpansion();
                        }
                        int speed = 0;
                        adjustScrollBounds(y);
                        if (y > mLowerBound) {
                            // scroll the list up a bit
                            speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;
                        } else if (y < mUpperBound) {
                            // scroll the list down a bit
                            speed = y < mUpperBound / 2 ? -16 : -4;
                        }
                        if (speed != 0) {
                            int ref = pointToPosition(0, mHeight / 2);
                            if (ref == AdapterView.INVALID_POSITION) {
                                //we hit a divider or an invisible view, check somewhere else
                                ref = pointToPosition(0, mHeight / 2 + getDividerHeight() + 64);
                            }
                            View v = getChildAt(ref - getFirstVisiblePosition());
                            if (v!= null) {
                                int pos = v.getTop();
                                setSelectionFromTop(ref, pos - speed);
                            }
                        }
                    }
                    break;
            }
            return true;
        }
        return super.onTouchEvent(ev);
    }

    private void startDragging(Bitmap bm, int y) {
        stopDragging();

        mWindowParams = new WindowManager.LayoutParams();
        mWindowParams.gravity = Gravity.TOP;
        mWindowParams.x = 0;
        mWindowParams.y = y - mDragPoint + mCoordOffset;
//
        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;

        ImageView v = new ImageView(mContext);
        int backGroundColor = mContext.getResources().getColor(R.color.dragndrop_background);
//        int backGroundColor = Color.parseColor("#e0103010");
        v.setBackgroundColor(backGroundColor);

        v.setImageBitmap(bm);
        mDragBitmap = bm;

        mWindowManager = (WindowManager)mContext.getSystemService("window");
        mWindowManager.addView(v, mWindowParams);
        mDragView = v;
    }

    private void dragView(int x, int y) {
//        if (mRemoveMode == SLIDE) {
//            float alpha = 1.0f;
//            int width = mDragView.getWidth();
//            if (x > width / 2) {
//                alpha = ((float)(width - x)) / (width / 2);
//            }
//            mWindowParams.alpha = alpha;
//        }
        mWindowParams.y = y - mDragPoint + mCoordOffset;
        mWindowManager.updateViewLayout(mDragView, mWindowParams);
    }

    private void stopDragging() {
        if (mDragView != null) {
            WindowManager wm = (WindowManager)mContext.getSystemService("window");
            wm.removeView(mDragView);
            mDragView.setImageDrawable(null);
            mDragView = null;
        }
        if (mDragBitmap != null) {
            mDragBitmap.recycle();
            mDragBitmap = null;
        }
    }

    public void setDragListener(DragListener l) {
        mDragListener = l;
    }

    public void setDropListener(DropListener l) {
        mDropListener = l;
    }

//    public void setRemoveListener(RemoveListener l) {
//        mRemoveListener = l;
//    }

    public interface DragListener {
        void drag(int from, int to);
    }
    public interface DropListener {
        void drop(int from, int to);
    }
    public interface RemoveListener {
        void remove(int which);
    }
}
위 코드중 정상적인 컴파일을 위해서 살펴보아야 할 부분이 두군데 있습니다.
위 코드에 다음과 같은 부분이 있습니다.
View dragger = item.findViewById(R.id.dragicon);
R.id.dragicon 이 바로 드래그를 할 대상이 되는 View가 됩니다.
또 다음과 같은 코드가 있습니다.
int backGroundColor = mContext.getResources().getColor(R.color.dragndrop_background);
이 부분은 드래그 앤 드롭시 백그라운드 색상을 지정해 주는 부분입니다.
위 색상 지정을 위해 strings.xml파일에 다음과 같은 항목을 추가해 주어야 합니다.
<color name="dragndrop_background">#e0103010</color>
이제 드래그 앤 드롭을 구현하기 위해서 ListActivity는 어떻게 구현해야 하는지 알아보겠습니다.
아래와 같이 DragListener와 DropListener를 구현하도록 ListActivity를 만듭니다.
public class MainActivity extends ListActivity implements DragListener, DropListener {
onCreate메써드에서 드래그 앤 드롭을 사용한다는 정보를 입력합니다.
listView = (DndListView) findViewById(android.R.id.list);
listView.setDragListener(this);
listView.setDropListener(this);
그리고 다음과 같은 메써드를 구현합니다.
public void drag(int from, int to) {
  // 드래그 이벤트가 발생시 구현해야 할 것들을 기술한다.
}

public void drop(int fr, int to) {
  // 드롭 이벤트 발생시 구현해야 할 것들을 기술한다.
}
Activity의 레이아웃 파일은 다음과 같이 작성해야 합니다.
<org.pyframe.tools.view.DndListView
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:drawSelectorOnTop="false"
        android:fastScrollEnabled="true"
        android:cacheColorHint="#00000000"
        android:layout_weight="1.0"
         />
cacheColorHint값을 주어야 드래그 앤 드롭시 선택된 아이템의 백그라운드 색상이 표시됩니다.

댓글

이 블로그의 인기 게시물

톰캣 세션 타임 아웃 설정

web.xml 파일이 있습니다. 이 파일을 열어서 session이라고 검색해 보십시오. <session-config>   <session-timeout>360</session-timeout> </session-config> 위 단락을 찾을 수 있습니다. session-timeout 시간 360이 바로 자동로그아웃 세션 시간입니다.  단위는 분이고요. 30분으로 하고 싶으시면 30으로 바꿔서 저장해주시면 되는 것이죠~ Tomcat 내에서 Session Timeout 를 설정하는 우선 순위가 존재 한다. session.setMaxInactiveInterval() 프로그램내에서 time out 를 설정했을 경우 Web application 내의 WEB-INF/web.xml Tomcat 내의 conf/web.xml 실제로 Tomcat(conf/web.xml)내에 Default 로 설정되어 있는 것은 다음과 같다. < HttpSession 메서드 > getCreationTime() - 세션 생성 시간 getLastAccessedTime() - 마지막 요청 시간 setMaxInactiveInterval() - 최대허용시간 설정 (초) getMaxInactiveInterval() - 최대허용시간 invalidate() - 세션 제거 < 타임아웃 설정하기 > - 일정 시간 동안 요청이 없으면 세션을 제거한다  1. DD에서 전체 세션 타임아웃 설정       web.xml 1. DD에서 전체 세션 타임아웃 설정       web.xml <web-app ... >     <servlet>        ...

java 특정 디렉토리에 있는 파일 목록을 읽어내기, 정렬해서 가져오기

폴더 리스트 가져오기 String path="C:\"; File dirFile=new File(path); File []fileList=dirFile.listFiles(); for(File tempFile : fileList) {   if(tempFile.isFile()) {     String tempPath=tempFile.getParent();     String tempFileName=tempFile.getName();     System.out.println("Path="+tempPath);     System.out.println("FileName="+tempFileName);     /*** Do something withd tempPath and temp FileName ^^; ***/   } } 정렬해서 가져오기 import java.io.FileFilter; import java.io.IOException; import java.util.Arrays; import java.util.Date; import org.apache.commons.io.comparator.LastModifiedFileComparator; import org.apache.commons.io.filefilter.FileFileFilter; public class LastModifiedFileComparatorTest { public static void main(String[] args) throws IOException { File directory = new File("."); // get just files, not directories File[] files = directory.listFiles((FileFilter) FileFileFilter.FILE); System.out.println("Defaul...

dmesg 메시지 실시간으로 보기

참조사이트 http://imitator.kr/Linux/556 # tail -f /var/log/messages # tail -f |dmesg //기본 2초 단위로 갱신 된다. # watch "dmesg | tail -f" //1초 단위로 갱신하면서 보여준다. # watch -n 1 "dmesg | tail -f" // 보여주는 줄을 20으로 늘린다. (기본 10줄) # watch -n 1 "dmesg | tail -f -n 20"