【问题标题】:Android: Drag and Drop issueAndroid:拖放问题
【发布时间】:2011-02-22 22:52:26
【问题描述】:

我正在为一堂课编写 SMIL 作曲家,我正计划使画布支持拖放,这样您就可以随意放置图片和文本。我已经查看了示例并自己做了一些,但是当我在我的项目中实现拖放时,它不起作用。以下是重要的主要代码:

public class ComposerActivity extends Activity {
    /** Called when the activity is first created. */

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.composer);

    Button add = (Button)findViewById(R.id.addBtn);
    ...

    add.setOnClickListener(mClick);
    ...
}

OnClickListener mClick = new OnClickListener() {
    @Override
    public void onClick(View v){        
        if(v.getId() == R.id.addBtn)
        {
            FrameLayout fl = (FrameLayout)findViewById(R.id.Canvas); 
            LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
            View itemView = inflater.inflate(R.layout.image_add, null);

            View image = (View)itemView.findViewById(R.id.image);   
            image.setBackgroundResource(R.drawable.icon); 

            fl.addView(itemView, new FrameLayout.LayoutParams(40, 40));  

            image.setOnTouchListener(drag);
        }
        ...

OnTouchListener drag = new OnTouchListener(){
    @Override 
    public boolean onTouch(View v, MotionEvent event){ 
        FrameLayout.LayoutParams par = (LayoutParams) v.getLayoutParams(); 
        switch(v.getId()){//What is being touched 
            case R.id.image:{//Which action is being taken 
                switch(event.getAction()){ 
                    case MotionEvent.ACTION_MOVE:{  
                        par.topMargin = (int)event.getRawY() - (v.getHeight()); 
                        par.leftMargin = (int)event.getRawX() - (v.getWidth()/2); 
                        v.setLayoutParams(par); 
                        break; 
                    }//inner case MOVE 
                    case MotionEvent.ACTION_UP:{ 
                        par.height = 40; 
                        par.width = 40; 
                        par.topMargin = (int)event.getRawY() - (v.getHeight()); 
                        par.leftMargin = (int)event.getRawX() - (v.getWidth()/2); 
                        v.setLayoutParams(par); 
                        break; 
                    }//inner case UP 
                    case MotionEvent.ACTION_DOWN:{ 
                        par.height = 60; 
                        par.width = 60; 
                        v.setLayoutParams(par); 
                        break; 
                    }//inner case UP 
                }//inner switch 
                break; 
            }//case image
        }//switch 
            return true; 
        }//onTouch 
    };//drag
}

这是composer.xml:

...
<FrameLayout android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_below="@+id/TopBar" 
    android:layout_above="@+id/addBtn" 
    android:id="@+id/Canvas"
    android:layout_gravity="top">

</FrameLayout>
...

还有 image_add.xml:

<View android:id="@+id/image" 
        android:layout_gravity="top"
        xmlns:android="http://schemas.android.com/apk/res/android"/> 

当我单击作曲家上的添加按钮时,它成功地将图像添加到画布上,当我触摸图像时,它的响应是变大,从 40x40 到 60x60 应该是这样。但它并没有跟随我的手指穿过屏幕,这就是我卡住的地方。

感谢任何输入。

【问题讨论】:

    标签: android drag-and-drop


    【解决方案1】:

    我研究了 Android Launcher 代码以了解它们是如何进行拖放的。我真的很喜欢他们的对象模型。他们所做的(可能对您有好处)是将处理拖放的责任转移到所有可拖动视图都在其中的 ViewGroup 中。触摸事件在此处而不是在您的视图中处理。

    两个关键类:

    DragLayer – 实现一个自定义 ViewGroup,它协调屏幕上视图的移动。 Launcher DragLayer 是 FrameLayout 的子类。

    DragController – 这个对象是支持拖放的控制器。

    他们所做的另一件事是在您放下拖动的对象之前不移动实际视图。但它看起来不是那样的,因为在屏幕上您会看到一个位图,该位图是由随着您的手指(或指针)移动而移动的视图构建的。

    我构建了一个简单的示例并编写了它。见http://blahti.wordpress.com/2011/01/17/moving-views-part-2/ 例子的源代码也有。

    【讨论】:

    • 我看过你的博客,虽然它做得很好,但它似乎有点复杂。您将如何将 ImageViews 和 TextViews 动态添加到 DragLayer,而不是硬编码它们?
    • 在另一篇博文(第 3 部分)中,我做到了。如果你看菜单选择代码,你会看到: // 向 DragLayer ImageView 添加一个新对象 newView = new ImageView (this); newView.setImageResource (R.drawable.hello); DragLayer.LayoutParams lp = new DragLayer.LayoutParams (60, 60, 80, 100); mDragLayer.addView (newView, lp); newView.setOnClickListener(this); newView.setOnLongClickListener(this);有点复杂,是的。我从 Android Launcher 中的代码开始,并对其进行了一些精简。我想在 developer.android.com 学习新的拖放。看看我最喜欢哪个。
    • 糟糕。看起来 cmets 是纯文本。对于那个很抱歉。请参阅我博客上第 3 部分中发布的代码。
    • 谢谢比尔,你的博客帮了大忙!
    • 这太棒了!正是我想要的。 @Bill Lahti 你是明星!
    【解决方案2】:

    如果您正在寻找预制的解决方案,这里有:

    https://github.com/thquinn/DraggableGridView

    这是我放在一起的自定义 ViewGroup,看起来它可能适合您的项目。祝你好运!

    【讨论】:

    • 这正是我所需要的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    相关资源
    最近更新 更多