拖放有onDrag问题的图像按钮

时间:2014-12-16 23:39:16

标签: java android drag-and-drop imagebutton applicationcontext

我正在开发一个Android应用程序,用户可以购买建筑物,这些建筑物是实现拖放api的图像按钮。我的问题是,当用户购买两个建筑物时,比如colonyHutOne和colonyHutTwo,存在一个问题,x和y坐标保存在onDrag中。在我的onDrag中,我传递了onDragListener中的建筑物编号,所以我知道我在onDrag类中处理的是什么建筑物。这样我就可以将坐标保存到适当的建筑物中。问题在于,无论我传递到onDrag的建筑物编号是什么,最近创建的建筑物都是采用坐标的建筑物。在onDrag中,它每次都会接收第二个建筑物,即使它是第一个被拖动的建筑物(建筑物的第一个)。我不知道这是否与传递给onDrag的上下文有关,或者是因为在拖拽之前声明了onDragListeners所以它只需要最后创建的图像按钮。我不知道如何解决这个问题。请帮忙。

以下是设置两个建筑物的拖拽监听器的代码:

findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
FrameLayout.LayoutParams  param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
newColonyHutFrame.addView(newColonyHutOne, param1);

findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
FrameLayout.LayoutParams  param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
newColonyHutFrame.addView(newColonyHutTwo, param1);

这是onDrag类:

public class ColonyHutDrag implements OnDragListener
{
    SharedPreferences prefs;
    Context passedContext;
    Database data;
    int buildingNum = 0;

    public ColonyHutDrag(Context applicationContext, int num) 
    {
        passedContext = applicationContext;
        buildingNum = num;
    }//end constructor

    @Override
    public boolean onDrag(View v, DragEvent event) 
    {
        float x = 0, y = 0;
        switch(event.getAction())
        {
        case DragEvent.ACTION_DRAG_STARTED:
            //drag has started
            break;

        case DragEvent.ACTION_DRAG_ENTERED:
            //being dragged
            break;

        case DragEvent.ACTION_DRAG_EXITED:
            //stop drag
            break;

        case DragEvent.ACTION_DRAG_LOCATION:
            //find drag location
            break;

        case DragEvent.ACTION_DROP:
            if (v == v.findViewById(R.id.bottomHalf))
            {
                //find position where dropped
                x = event.getX();
                y = event.getY();

                //save the coordinates that the building was dropped at
                data = new Database(passedContext);
                data.open();
                if (buildingNum == 1)
                {
                    data.colonyHutOneXEntry(x);
                    data.colonyHutOneYEntry(y);
                    Toast.makeText(passedContext, "Going in1 -> x: " + x + " y: " + y, Toast.LENGTH_SHORT).show();
                }//end if
                else if (buildingNum == 2)
                {
                    data.colonyHutTwoXEntry(x);
                    data.colonyHutTwoYEntry(y);
                    Toast.makeText(passedContext, "Going in2 -> x: " + x + " y: " + y, Toast.LENGTH_SHORT).show();
                }//end else if

                data.close();

                //use this to fix building loadup glitch
                View view = (View) event.getLocalState();
                ViewGroup group = (ViewGroup) view.getParent();
                group.removeView(view);
                FrameLayout contain = (FrameLayout) v;
                contain.addView(view);
                view.setX(x - (view.getWidth()/2));
                view.setY(y - (view.getHeight()/2));
                view.setVisibility(View.VISIBLE);
            }//end if
            else
            {
                View view = (View) event.getLocalState();
                view.setVisibility(View.VISIBLE);
            }//end else
            break;

        default:
            break;
        }//end switch
        return true;
    }//end onDrag function
}//end ColonyHutOneDrag class

这是用于拖放的onTouchlistener:

public class BuildingsClick implements OnTouchListener 
{   
    @Override
    public boolean onTouch(View v, MotionEvent event) 
    {
        ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());

        String[] mimeTypes = { ClipDescription.MIMETYPE_TEXT_PLAIN }; 
        ClipData data = new ClipData(v.getTag().toString(), mimeTypes, item); 
        DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v); 

        v.startDrag(data, shadowBuilder, v, 0);
        v.setVisibility(View.INVISIBLE);

        return false;   
    }//end onTouch function

}//end BuildingsClick class

我非常感谢任何帮助。我不知道如何解决这个问题。这几乎就像处理第二座建筑物一样,然后第一座建筑物再也无法被引用。 谢谢你们。

编辑:

BuildingsClick类中的代码

//find which building is being dragged
if (v.getTag() == "NewColonyHutOne")
{
    ColonyHutDrag.setType(ColonyHutOneDrag.getType());
}//end if
else if (v.getTag() == "NewColonyHutTwo")
{
    ColonyHutDrag.setType(ColonyHutTwoDrag.getType());
}//end if

ColonyHutOneDrag类的代码:

public class ColonyHutOneDrag extends ColonyHut
{

    @Override
    public int getType() 
    {
        return 1;
    }//end getType

}//end ColonyHutOneDrag 

ColonyHutTwoDrag类的代码与第一个类相同,但返回2.

这是ColonyHutDrag中的getType:

public void setType(int type)
{
    buildingNum = type;
}//end setType

1 个答案:

答案 0 :(得分:1)

您错误地再次指定了OnDragListener

你不能

findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 1));
FrameLayout.LayoutParams  param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);

然后

findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext(), 2));
FrameLayout.LayoutParams  param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);

原因是因为你的第二个电话会覆盖你的第一个电话,你永远不会听到要拖动的小屋类型1,因为你在你的构造函数中传递了你正在听的小屋。

解决方法是改变你的听众分配,如下所示:

findViewById(R.id.topHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext()));
findViewById(R.id.bottomHalf).setOnDragListener(new ColonyHutDrag(getApplicationContext());
FrameLayout.LayoutParams  param1 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);

我们将制作一个抽象类ColonyHut,并定义public int getType();

除去ColonyHutListener的构造函数,我们也不需要它。然后,如果您还没有一个名为ColonyHutOne的课程,那么您将打造一个名为ColonyHut的课程。在该课程中,您需要扩展getType(),并定义public int getType() { return 1; } ,如下所示:

ColonyHutDrag

然后我们将在setType()类中定义一个名为public void setType(int type) { buildingNum = type; } 的函数,如下所示:

ColonyHutOne

之后你想要ColonyHut作为ColonyHut currentlySelectedHut = view.getHutFromView() onTouchListenercolonyHutDrag.setType(currentlySelectedHut.getType()) v.startDrag(),然后再致电ColonyHutTwo getType()它应该有效。对view.getHutFromView()执行相同操作,但显然您应该colonyHutDrag返回2。

我将保留定义BuildingsClick,并在{{1}}课程中显示{{1}}。毕竟一切都不是自由的: - )。