拖拽控件

public class MyGridLayout extends GridLayout {

    public MyGridLayout(Context context) {
        //super(context);
        this(context,null);
    }

    public MyGridLayout(Context context, AttributeSet attrs) {
        //super(context, attrs);
        this(context,attrs,-1);
    }

    public MyGridLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //设置平移的过渡动画效果
        this.setLayoutTransition(new LayoutTransition());
    }

    /**
     * 提供给activity调用的,负责将activity中的数据,传递给Gridlayout进行展示操作
     *
     * 2016年12月17日   上午9:51:39
     */
    public void setItemDatas(List<String> datas){
        //因为每个集合中的元素都对应有一个textview来进行展示,所以需要根据集合的长度创建相应个数的textview来展示数据
        for (String string : datas) {
            addTextView(string);
        }
    }

    /**
     * 根据集合的个数创建相应的textview,并添加到gridlayout中展示
     *
     * 2016年12月17日   上午9:53:19
     */
    public void addTextView(String string) {
        final TextView textView = new TextView(getContext());
        textView.setText(string);
        textView.setTextColor(Color.BLACK);
        textView.setGravity(Gravity.CENTER);
        textView.setBackgroundResource(R.drawable.selector_gridlayout_textview_bg);
        textView.setPadding(15, 5, 15, 5);//设置textview中文本距离textview内边框的上下左右的距离

        GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
        layoutParams.width = LayoutParams.WRAP_CONTENT;
        layoutParams.height = LayoutParams.WRAP_CONTENT;
        layoutParams.setMargins(5, 5, 5, 5);//设置textview距离父控件的上下左右的位置

        //将layoutparams设置给TextView,使距离父控件上下左右的距离的操作生效
        textView.setLayoutParams(layoutParams);

        //设置TextView的点击事件,实现两个Gridlayout数据的添加和删除操作
        textView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                //因为实在自定义Gridlayout中实现的textview的点击事件,但是数据的操作是跟两个Gridlayout有关系的,只有activity中有两个GridLayout
                //因为点击textView之后,两个GridLayout就要实现添加和删除点击的textview的操作,但是两个GridLayout实在activity中的,所以需要将被点击的TextView传递到activity才能实现两个Gridlayout之间的数据操作
                if (listener != null) {
                    listener.itemClick(textView);
                }
            }
        });

        //设置TextView的长按事件,实现拖拽效果
        //根据是否可以拖拽的标示设置textview是否能够进行拖拽操作
        if (isDrag) {
            textView.setOnLongClickListener(longClickListener);
        }else{
            textView.setOnLongClickListener(null);
        }

        //监听GridLayout的拖拽监听,实现条目位置改变的操作
        this.setOnDragListener(dragListener);

        //将textview设置给GridLayout进行显示操作
        this.addView(textView);
    }

    /**
     * GridLayout的拖拽的监听
     */
    private OnDragListener dragListener = new OnDragListener() {

        //当Gridlayout有拖拽的操作的时候,调用此方法
        //参数1:拖拽监听设置的控件
        //参数2:拖拽的事件
        @Override
        public boolean onDrag(View v, DragEvent event) {
            switch (event.getAction()) {
            case DragEvent.ACTION_DRAG_STARTED://开始拖拽了
                System.out.println("拖拽开始");
                //以TextView为蓝本创建矩形
                createRect();
                break;
            case DragEvent.ACTION_DRAG_ENTERED://控件开始拖拽后,进入控件拖拽范围的操作
                System.out.println("进入拖拽范围");
                break;
            case DragEvent.ACTION_DRAG_EXITED://控件开始拖拽后,退出控件拖拽范围的操作
                System.out.println("退出拖拽范围");
                break;
            case DragEvent.ACTION_DRAG_LOCATION://控件开始拖拽后,在拖拽范围内移动的操作
                System.out.println("拖拽控件移动");
                //根据移动的坐标,去判断移动的坐标是否已经完全移动相应的textview上了
                int index = getIndex(event);
                //判断如果有移动的位置,并且移动的textview不等于空,并且移动的textview不在原来的 位置,就可以进行移动操作
                if (index > -1 && currentView != null && currentView != MyGridLayout.this.getChildAt(index)) {
                    MyGridLayout.this.removeView(currentView);
                    //将view对象,添加到那个位置
                    //index : view对象添加显示的位置
                    MyGridLayout.this.addView(currentView, index);
                }
                break;
            case DragEvent.ACTION_DRAG_ENDED://结束拖拽
                System.out.println("拖拽结束");
                //当textview拖拽结束,设置textview重新可以使用
                if (currentView != null) {
                    currentView.setEnabled(true);
                }
                break;
            case DragEvent.ACTION_DROP://结束拖拽,手指松开(在拖拽范围内执行的操作)
                System.out.println("拖拽结束,手指松开");
                break;
            }
            //返回true:拖拽的操作可以实现,返回false:不能实现
            return true;
        }
    };

    /**
     * 判断移动的坐标,是否在textview相对应的矩形的中
     * 返回矩形所代表的textview的位置
     * 2016年12月17日   上午11:46:07
     */
    protected int getIndex(DragEvent event) {
        for (int i = 0; i < rects.length; i++) {
            //判断移动的坐标是否在textview对应的矩形中
            if (rects[i].contains((int)event.getX(), (int)event.getY())) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 创建矩形
     *
     * 2016年12月17日   上午11:39:19
     */
    protected void createRect() {
        //创建包含左上角和右下角的坐标的矩形的数组
        //this.getChildCount() : 获取自定义控件的孩子的个数
        rects = new Rect[this.getChildCount()];
        for (int i = 0; i < this.getChildCount(); i++) {
            //根据索引获取子控件的对象
            View view = this.getChildAt(i);
            //矩形的坐标是根据实际的textview的坐标来定的
            //参数1,2:左上角的x和y的坐标
            //参数3,4:右下角的x和y的坐标
            Rect rect = new Rect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());

            rects[i] = rect;
        }
    }

    /**设置保存拖拽的textview**/
    private View currentView;

    /**
     * textview的长按监听
     */
    private OnLongClickListener longClickListener = new OnLongClickListener() {

        //v:被长按的控件的view对象
        @Override
        public boolean onLongClick(View v) {

            //实现textview的拖拽的效果
            //开始拖拽
            //参数1:拖拽所需的数据,一般null
            //参数2:拖拽的阴影的效果,DragShadowBuilder(v):根据实际的控件的效果实现阴影效果
            //参数3:设置拖拽的控件的状态,一般null
            //参数4:设置拖拽的控件的执行的事件,一般0
            v.startDrag(null, new DragShadowBuilder(v), null, 0);

            //设置textview在拖拽的时候不可用
            v.setEnabled(false);

            //当textView拖拽的时候,保存TextView方便在Gridlayout改为条目位置的进行背景,控制的位置的设置
            currentView = v;

            //返回true执行长按事件,返回false:不执行
            return true;
        }
    };

    private boolean isDrag;
    /**
     * 提供给activity调用的,方便在activity中设置两个Gridlayout中的textview是否可以进行拖拽效果
     *
     * 2016年12月17日   上午11:17:53
     */
    public void isDrag(boolean isDrag){
        this.isDrag = isDrag;
        //根据是否可以拖拽的标示,设置两个GridLayout是否可以进行条目位置移动的操作
        if (isDrag) {
            this.setOnDragListener(dragListener);
        }else{
            this.setOnDragListener(null);
        }
    }

    /**保存activity传递过来的接口实现对象**/
    private OnItemClickListener listener;

    private Rect[] rects;
    /**
     * 提供给activity调用,负责activity将接口的实现对象传递到自定义控件中
     *
     * 2016年12月17日   上午10:33:45
     */
    public void setOnItemClickListener(OnItemClickListener listener){
        this.listener = listener;
    }

    public interface OnItemClickListener{
        /**
         * 条目点击的回调方法
         * TextView : 被点击的textview
         * 2016年12月17日   上午10:32:09
         */
        public void itemClick(TextView view);
    }
public class SelectItemActivity extends Activity {

    private List<String> titles1;

    private String[] TITLES = new String[]{"娱乐","服饰","音乐","视频","段子","搞笑","科学","房产","名站"};

    private List<String> titles2;

    private MyGridLayout mGrid2;

    private MyGridLayout mGrid1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_select_item);
        StatusBarUtil.setColor(this, Color.WHITE);

        getValue();
        initView();
    }

    /**
     * 获取拖拽界面所需的数据
     *
     * 2016年12月17日   上午9:22:23
     */
    private void getValue() {
        titles1 = (List<String>) getIntent().getSerializableExtra("titles");
        //获取底部所需数据
        titles2 = new ArrayList<String>();
        titles2.clear();
        for (int i = 0; i < TITLES.length; i++) {
            titles2.add(TITLES[i]);
        }
    }

    /**
     * 初始化控件
     *
     * 2016年12月17日   上午10:01:33
     */
    private void initView() {
        mGrid1 = (MyGridLayout) findViewById(R.id.selectitem_mgl_gridlayout1);
        mGrid2 = (MyGridLayout) findViewById(R.id.selectitem_mgl_gridlayout2);

        //调用设置是否可以拖拽的方法,设置两个GridLayout中的textview是否可以进行拖拽的效果
        mGrid1.isDrag(true);
        mGrid2.isDrag(false);

        //将数据传递给gridlayout进行显示
        mGrid1.setItemDatas(titles1);
        mGrid2.setItemDatas(titles2);

        //调用回调,获取被点击textview,实现数据的操作
        mGrid1.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void itemClick(TextView view) {
                //mGrid1删除点击的textview
                //mGrid2添加点击的textview
                mGrid1.removeView(view);
                mGrid2.addTextView(view.getText().toString());
            }
        });
        mGrid2.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void itemClick(TextView view) {
                //mGrid2删除点击的textview
                //mGrid1添加点击的textview
                mGrid2.removeView(view);
                mGrid1.addTextView(view.getText().toString());
            }
        });
    }

    /**
     * 返回按钮的点击事件
     *
     * 2016年12月17日   下午12:01:33
     */
    public void back(View view){
        finish();
    }
时间: 2024-10-14 07:37:02

拖拽控件的相关文章

独家原创,拖拽任意控件移动任意目标,拖拽控件移动整个窗体

独家原创,拖拽任意控件移动任意目标,拖拽控件移动整个窗体,在无边框窗体及其友好的实现拖拽移动窗体 http://www.cnblogs.com/vonly/ only原创首发,vonly.net 1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Configuration; 5 using System.Diagnostics; 6 using Sys

android 实现图片选择拖拽控件

1.使用RecyclerView 使用RecyclerView可以轻松实现图片切换时的动画过程,这点要好于GridView. 2. 拖拽的实现 Dragmanager 继承View.OnDragListener,对拖拽过程中进行操作, Action_drag_started 获取到操作的Item Action_Drag_location 根据每个停留的位置判断是否交换item的位置. Action_Drag_ended 跟新位置 DragSortAdapter 抽象类,为recyclerView

ViewDragHelper(拖拽控件之3种方法)

+++++++++++++++++++++++++++++++方法1++++++++++++++++++++++++++++++++++++ activity_main.xml布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_wi

开发winform程序,在拖拽控件大小时,VS会卡死

你可以看看你最近有没有装什么新的软件,比如说:有道词典就会与VS有冲突,导致卡死,可以把进程关闭.

关于在storyboard拖按钮控件,手动设置代码不成功的问题

首先,在 storyboard 中拖拽一个按钮控件.设置好约束条件 然后把该控件作为属性,拖线到控制器当中 拿到控件属性后,可以在控制器当中用代码进行设置图片信息,我们以下载网络图片为例: 1 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 2 { 3 4 // 1.开启异步线程 5 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 6 7

将文件拖到控件中获得文件路径

文件拖过来的代码为: (System.Array)e.Data.GetData(DataFormats.FileDrop) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; usin

一个能接受外部拖拽的控件(文字或文件)

恩....也是这2天写的一个小东西的需求, 可以拖拽外部文本文件, 或者选择的一段文本到Memo里显示 查了一下资料, 主要从2个方面实现: 1.拖拽文件实现WM_DROPFILES就可以了 2.拖拽文本需要实现IDropTarget接口 针对这个功能, 重新封装了一个Memo出来: TDropMemo = class(TMemo, IUnknown, IDropTarget) private FDropAccept: Boolean; FDTDropAccept: HResult; FFE:

不拖控件ASP.NET——一般处理程序

    习惯了微软提供的一系列Web控件,用着很方便,最近看了一种新的方式不用拖控件就能实现同样的功能,究竟拖控件好还是不拖控件好,随着以后学习的深入,答案会慢慢揭晓,希望一直关注哦!今天我们来看看一般处理程序. 1.      一般处理程序(HttpHandler) ?  引入     我们从一个网站打开的流程讲起.如下图:     流程细说:用webForm开发一个模拟的登陆页面,用户打开登陆页面,填入相应的用户信息:用户名和密码,点击[登陆]按钮,浏览器将用户名和密码发送给网站服务器,网站

.NET成人礼 | 还记得20年前一起拖过的控件吗?

本文是MVP Ediwang写的回忆一个80后的拖控件的感悟,与君共勉: 每一代人都有记忆里的味道.煤球炉.黑白电视机是属于父母的记忆.而“拖控件”式编程,启蒙了无数像我这样的80后(嗯,89也算80后). 经典旧世 2000 年那个时候,上海这样的城市里也不是每家每户都有电脑,我家也没有电脑.我在学校经常听几位家里条件不错的同学说他们玩电脑的事情.CIH.千年虫等名词让我对电脑有着非常强烈的好奇心.而我第一次体验到计算机,是在我母亲单位的机房里.它是一台卧式机箱.15寸 CRT 凸面屏显示器的