zoukankan      html  css  js  c++  java
  • 可随意交换位置的gridview

    自定义gridview

    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Point;
    import android.os.Handler;
    import android.os.SystemClock;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.animation.AlphaAnimation;
    import android.view.animation.Animation;
    import android.view.animation.AnimationSet;
    import android.view.animation.ScaleAnimation;
    import android.view.animation.TranslateAnimation;
    import android.widget.ImageView;
    import android.widget.AdapterView.OnItemClickListener;
    
    import java.util.ArrayList;
    import java.util.Collections;
    
    /**
     * Created by Administrator on 2017/2/27.
     */
    public class DraggableGridView extends ViewGroup implements View.OnTouchListener, View.OnClickListener, View.OnLongClickListener {
        //layout vars
        public static float childRatio = .9f;
        protected int colCount, childSize, padding, dpi, scroll = 0;
        protected float lastDelta = 0;
        protected Handler handler = new Handler();
        //dragging vars
        protected int dragged = -1, lastX = -1, lastY = -1, lastTarget = -1;
        protected boolean enabled = true, touching = false;
        //anim vars
        public static int animT = 150;
        protected ArrayList<Integer> newPositions = new ArrayList<Integer>();
        //listeners
        protected OnRearrangeListener onRearrangeListener;
        protected OnClickListener secondaryOnClickListener;
        private OnItemClickListener onItemClickListener;
    
        //CONSTRUCTOR AND HELPERS
        public DraggableGridView(Context context, AttributeSet attrs) {
            super(context, attrs);
            setListeners();
            handler.removeCallbacks(updateTask);
            handler.postAtTime(updateTask, SystemClock.uptimeMillis() + 500);
            setChildrenDrawingOrderEnabled(true);
    
            DisplayMetrics metrics = new DisplayMetrics();
            ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metrics);
            dpi = metrics.densityDpi;
        }
    
        protected void setListeners() {
            setOnTouchListener(this);
            super.setOnClickListener(this);
            setOnLongClickListener(this);
        }
    
        @Override
        public void setOnClickListener(OnClickListener l) {
            secondaryOnClickListener = l;
        }
    
        protected Runnable updateTask = new Runnable() {
            public void run() {
                if (dragged != -1) {
                    if (lastY < padding * 3 && scroll > 0)
                        scroll -= 20;
                    else if (lastY > getBottom() - getTop() - (padding * 3) && scroll < getMaxScroll())
                        scroll += 20;
                } else if (lastDelta != 0 && !touching) {
                    scroll += lastDelta;
                    lastDelta *= .9;
                    if (Math.abs(lastDelta) < .25)
                        lastDelta = 0;
                }
                clampScroll();
                onLayout(true, getLeft(), getTop(), getRight(), getBottom());
    
                handler.postDelayed(this, 25);
            }
        };
    
        //OVERRIDES
        @Override
        public void addView(View child) {
            super.addView(child);
            newPositions.add(-1);
        }
    
        ;
    
        @Override
        public void removeViewAt(int index) {
            super.removeViewAt(index);
            newPositions.remove(index);
        }
    
        ;
    
        //LAYOUT
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            //compute width of view, in dp
            float w = (r - l) / (dpi / 160f);
    
            //determine number of columns, at least 2
            colCount = 2;
            int sub = 240;
            w -= 280;
            while (w > 0) {
                colCount++;
                w -= sub;
                sub += 40;
            }
    
            //determine childSize and padding, in px
            childSize = (r - l) / colCount;
            childSize = Math.round(childSize * childRatio);
            padding = ((r - l) - (childSize * colCount)) / (colCount + 1);
    
            for (int i = 0; i < getChildCount(); i++)
                if (i != dragged) {
                    Point xy = getCoorFromIndex(i);
                    getChildAt(i).layout(xy.x, xy.y, xy.x + childSize, xy.y + childSize);
                }
        }
    
        @Override
        protected int getChildDrawingOrder(int childCount, int i) {
            if (dragged == -1)
                return i;
            else if (i == childCount - 1)
                return dragged;
            else if (i >= dragged)
                return i + 1;
            return i;
        }
    
        public int getIndexFromCoor(int x, int y) {
            int col = getColOrRowFromCoor(x), row = getColOrRowFromCoor(y + scroll);
            if (col == -1 || row == -1) //touch is between columns or rows
                return -1;
            int index = row * colCount + col;
            if (index >= getChildCount())
                return -1;
            return index;
        }
    
        protected int getColOrRowFromCoor(int coor) {
            coor -= padding;
            for (int i = 0; coor > 0; i++) {
                if (coor < childSize)
                    return i;
                coor -= (childSize + padding);
            }
            return -1;
        }
    
        protected int getTargetFromCoor(int x, int y) {
            if (getColOrRowFromCoor(y + scroll) == -1) //touch is between rows
                return -1;
            //if (getIndexFromCoor(x, y) != -1) //touch on top of another visual
            //return -1;
    
            int leftPos = getIndexFromCoor(x - (childSize / 4), y);
            int rightPos = getIndexFromCoor(x + (childSize / 4), y);
            if (leftPos == -1 && rightPos == -1) //touch is in the middle of nowhere
                return -1;
            if (leftPos == rightPos) //touch is in the middle of a visual
                return -1;
    
            int target = -1;
            if (rightPos > -1)
                target = rightPos;
            else if (leftPos > -1)
                target = leftPos + 1;
            if (dragged < target)
                return target - 1;
    
            //Toast.makeText(getContext(), "Target: " + target + ".", Toast.LENGTH_SHORT).show();
            return target;
        }
    
        protected Point getCoorFromIndex(int index) {
            int col = index % colCount;
            int row = index / colCount;
            return new Point(padding + (childSize + padding) * col,
                    padding + (childSize + padding) * row - scroll);
        }
    
        public int getIndexOf(View child) {
            for (int i = 0; i < getChildCount(); i++)
                if (getChildAt(i) == child)
                    return i;
            return -1;
        }
    
        //EVENT HANDLERS
        public void onClick(View view) {
            if (enabled) {
                if (secondaryOnClickListener != null)
                    secondaryOnClickListener.onClick(view);
                if (onItemClickListener != null && getLastIndex() != -1)
                    onItemClickListener.onItemClick(null, getChildAt(getLastIndex()), getLastIndex(), getLastIndex() / colCount);
            }
        }
    
        public boolean onLongClick(View view) {
            if (!enabled)
                return false;
            int index = getLastIndex();
            if (index != -1) {
                dragged = index;
                animateDragged();
                return true;
            }
            return false;
        }
    
        public boolean onTouch(View view, MotionEvent event) {
            int action = event.getAction();
            switch (action & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    enabled = true;
                    lastX = (int) event.getX();
                    lastY = (int) event.getY();
                    touching = true;
                    break;
                case MotionEvent.ACTION_MOVE:
                    int delta = lastY - (int) event.getY();
                    if (dragged != -1) {
                        //change draw location of dragged visual
                        int x = (int) event.getX(), y = (int) event.getY();
                        int l = x - (3 * childSize / 4), t = y - (3 * childSize / 4);
                        getChildAt(dragged).layout(l, t, l + (childSize * 3 / 2), t + (childSize * 3 / 2));
    
                        //check for new target hover
                        int target = getTargetFromCoor(x, y);
                        if (lastTarget != target) {
                            if (target != -1) {
                                animateGap(target);
                                lastTarget = target;
                            }
                        }
                    } else {
                        scroll += delta;
                        clampScroll();
                        if (Math.abs(delta) > 2)
                            enabled = false;
                        onLayout(true, getLeft(), getTop(), getRight(), getBottom());
                    }
                    lastX = (int) event.getX();
                    lastY = (int) event.getY();
                    lastDelta = delta;
                    break;
                case MotionEvent.ACTION_UP:
                    if (dragged != -1) {
                        View v = getChildAt(dragged);
                        if (lastTarget != -1)
                            reorderChildren();
                        else {
                            Point xy = getCoorFromIndex(dragged);
                            v.layout(xy.x, xy.y, xy.x + childSize, xy.y + childSize);
                        }
                        v.clearAnimation();
                        if (v instanceof ImageView)
                            ((ImageView) v).setAlpha(255);
                        lastTarget = -1;
                        dragged = -1;
                    }
                    touching = false;
                    break;
            }
            if (dragged != -1)
                return true;
            return false;
        }
    
        //EVENT HELPERS
        protected void animateDragged() {
            View v = getChildAt(dragged);
            int x = getCoorFromIndex(dragged).x + childSize / 2, y = getCoorFromIndex(dragged).y + childSize / 2;
            int l = x - (3 * childSize / 4), t = y - (3 * childSize / 4);
            v.layout(l, t, l + (childSize * 3 / 2), t + (childSize * 3 / 2));
            AnimationSet animSet = new AnimationSet(true);
            ScaleAnimation scale = new ScaleAnimation(.667f, 1, .667f, 1, childSize * 3 / 4, childSize * 3 / 4);
            scale.setDuration(animT);
            AlphaAnimation alpha = new AlphaAnimation(1, .5f);
            alpha.setDuration(animT);
    
            animSet.addAnimation(scale);
            animSet.addAnimation(alpha);
            animSet.setFillEnabled(true);
            animSet.setFillAfter(true);
    
            v.clearAnimation();
            v.startAnimation(animSet);
        }
    
        protected void animateGap(int target) {
            for (int i = 0; i < getChildCount(); i++) {
                View v = getChildAt(i);
                if (i == dragged)
                    continue;
                int newPos = i;
                if (dragged < target && i >= dragged + 1 && i <= target)
                    newPos--;
                else if (target < dragged && i >= target && i < dragged)
                    newPos++;
    
                //animate
                int oldPos = i;
                if (newPositions.get(i) != -1)
                    oldPos = newPositions.get(i);
                if (oldPos == newPos)
                    continue;
    
                Point oldXY = getCoorFromIndex(oldPos);
                Point newXY = getCoorFromIndex(newPos);
                Point oldOffset = new Point(oldXY.x - v.getLeft(), oldXY.y - v.getTop());
                Point newOffset = new Point(newXY.x - v.getLeft(), newXY.y - v.getTop());
    
                TranslateAnimation translate = new TranslateAnimation(Animation.ABSOLUTE, oldOffset.x,
                        Animation.ABSOLUTE, newOffset.x,
                        Animation.ABSOLUTE, oldOffset.y,
                        Animation.ABSOLUTE, newOffset.y);
                translate.setDuration(animT);
                translate.setFillEnabled(true);
                translate.setFillAfter(true);
                v.clearAnimation();
                v.startAnimation(translate);
    
                newPositions.set(i, newPos);
            }
        }
    
        protected void reorderChildren() {
            //FIGURE OUT HOW TO REORDER CHILDREN WITHOUT REMOVING THEM ALL AND RECONSTRUCTING THE LIST!!!
            if (onRearrangeListener != null)
                onRearrangeListener.onRearrange(dragged, lastTarget);
            ArrayList<View> children = new ArrayList<View>();
            for (int i = 0; i < getChildCount(); i++) {
                getChildAt(i).clearAnimation();
                children.add(getChildAt(i));
            }
            removeAllViews();
            while (dragged != lastTarget)
                if (lastTarget == children.size()) // dragged and dropped to the right of the last element
                {
                    children.add(children.remove(dragged));
                    dragged = lastTarget;
                } else if (dragged < lastTarget) // shift to the right
                {
                    Collections.swap(children, dragged, dragged + 1);
                    dragged++;
                } else if (dragged > lastTarget) // shift to the left
                {
                    Collections.swap(children, dragged, dragged - 1);
                    dragged--;
                }
            for (int i = 0; i < children.size(); i++) {
                newPositions.set(i, -1);
                addView(children.get(i));
            }
            onLayout(true, getLeft(), getTop(), getRight(), getBottom());
        }
    
        public void scrollToTop() {
            scroll = 0;
        }
    
        public void scrollToBottom() {
            scroll = Integer.MAX_VALUE;
            clampScroll();
        }
    
        protected void clampScroll() {
            int stretch = 3, overreach = getHeight() / 2;
            int max = getMaxScroll();
            max = Math.max(max, 0);
    
            if (scroll < -overreach) {
                scroll = -overreach;
                lastDelta = 0;
            } else if (scroll > max + overreach) {
                scroll = max + overreach;
                lastDelta = 0;
            } else if (scroll < 0) {
                if (scroll >= -stretch)
                    scroll = 0;
                else if (!touching)
                    scroll -= scroll / stretch;
            } else if (scroll > max) {
                if (scroll <= max + stretch)
                    scroll = max;
                else if (!touching)
                    scroll += (max - scroll) / stretch;
            }
        }
    
        protected int getMaxScroll() {
            int rowCount = (int) Math.ceil((double) getChildCount() / colCount), max = rowCount * childSize + (rowCount + 1) * padding - getHeight();
            return max;
        }
    
        public int getLastIndex() {
            return getIndexFromCoor(lastX, lastY);
        }
    
        //OTHER METHODS
        public void setOnRearrangeListener(OnRearrangeListener l) {
            this.onRearrangeListener = l;
        }
    
        public void setOnItemClickListener(OnItemClickListener l) {
            this.onItemClickListener = l;
        }
    }

    使用:

    import android.annotation.TargetApi;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.Gravity;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        private DraggableGridView vgv;
    
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            vgv = (DraggableGridView) findViewById(R.id.vgv);
            for (int i = 0; i < 10; i++) {
                TextView textView = new TextView(this);
                textView.setText(i + "");
                textView.setBackground(getResources().getDrawable(R.drawable.tv_bg));
                textView.setGravity(Gravity.CENTER);
                vgv.addView(textView);
            }
    
            vgv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    vgv.removeViewAt(position);
                }
            });
        }
    }
  • 相关阅读:
    Centos安装Nginx过程步骤详细解析
    查看是否已经安装nginx
    使用uwsgi --http :80 --wsgi-file test.py 在浏览器上无法访问
    uwsgi 常用参数
    Python生成requirements.txt方法
    快排
    绝对路径和相对路径
    perspective结合transform的3D效果
    mobile&nbsp;web&nbsp;手机开发
    Date对象需要注意的点
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/6473134.html
Copyright © 2011-2022 走看看