如何将 TextView 拖到正确的目标其他 TextView

Posted

技术标签:

【中文标题】如何将 TextView 拖到正确的目标其他 TextView【英文标题】:How to drag the TextView to the correct target other TextView 【发布时间】:2013-06-25 00:28:49 【问题描述】:

我已经给出了我所拥有的完整代码。

下面的代码可以非常流畅地拖放,但它不像下面描述的那样工作。

    拖动数据是(Apple、Orage、Ball) 放置目标位置是(A 代表,O 代表,B 代表)

因此,如果将“Apple”拖放到“A for”,它将是正确的并将文本更新为“A for Apple”,并且拖动时的文本“Apple”将被隐藏......但是如果我们拖动“Apple”拖放到“O for”或“B for”将失败,因为“O for Orange”和“B for Ball”。

根据下面的代码,我应该添加什么。

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical"
android:padding="10dp"
android:paddingLeft="50dp"
android:paddingRight="50dp" >


<TextView
    android:id="@+id/option_1"
    android:layout_
    android:layout_
    android:layout_margin="5dp"
    android:background="@drawable/option"
    android:gravity="center"
    android:text="Apple"
    android:textStyle="bold" />

<TextView
    android:id="@+id/option_2"
    android:layout_
    android:layout_
    android:layout_margin="5dp"
    android:background="@drawable/option"
    android:gravity="center"
    android:text="Orange"
    android:textStyle="bold" />

<TextView
    android:id="@+id/option_3"
    android:layout_
    android:layout_
    android:layout_margin="5dp"
    android:background="@drawable/option"
    android:gravity="center"
    android:text="Ball"
    android:textStyle="bold" />

<TextView
    android:id="@+id/choice_1"
    android:layout_
    android:layout_
    android:layout_margin="5dp"
    android:background="@drawable/choice"
    android:gravity="center"
    android:text="A for " />

<TextView
    android:id="@+id/choice_2"
    android:layout_
    android:layout_
    android:layout_margin="5dp"
    android:background="@drawable/choice"
    android:gravity="center"
    android:text="O for" />

<TextView
    android:id="@+id/choice_3"
    android:layout_
    android:layout_
    android:layout_margin="5dp"
    android:background="@drawable/choice"
    android:gravity="center"
    android:text="B for " />

</LinearLayout>

活动:

public class picture_to_word_24_color extends Activity 

//text views being dragged and dropped onto
private TextView option1, option2, option3, choice1, choice2, choice3;
public CharSequence dragData;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.picture_to_word_24_color);

    //get both sets of text views

    //views to drag
    option1 = (TextView)findViewById(R.id.option_1);
    option2 = (TextView)findViewById(R.id.option_2);
    option3 = (TextView)findViewById(R.id.option_3);

    //views to drop onto
    choice1 = (TextView)findViewById(R.id.choice_1);
    choice2 = (TextView)findViewById(R.id.choice_2);
    choice3 = (TextView)findViewById(R.id.choice_3);

    //set touch listeners
    option1.setOnTouchListener(new ChoiceTouchListener());
    option2.setOnTouchListener(new ChoiceTouchListener());
    option3.setOnTouchListener(new ChoiceTouchListener());

    //set drag listeners
    choice1.setOnDragListener(new ChoiceDragListener());
    choice2.setOnDragListener(new ChoiceDragListener());
    choice3.setOnDragListener(new ChoiceDragListener());


/**
 * ChoiceTouchListener will handle touch events on draggable views
 *
 */
private final class ChoiceTouchListener implements OnTouchListener 
    @SuppressLint("NewApi")
    public boolean onTouch(View view, MotionEvent motionEvent) 
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) 
            /*
             * Drag details: we only need default behavior
             * - clip data could be set to pass data as part of drag
             * - shadow can be tailored
             */
            ClipData data = ClipData.newPlainText("", "");
            DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
            //start dragging the item touched
            view.startDrag(data, shadowBuilder, view, 0);
            return true;
         else 
            return false;
        
    
 

/**
 * DragListener will handle dragged views being dropped on the drop area
 * - only the drop action will have processing added to it as we are not
 * - amending the default behavior for other parts of the drag process
 *
 */
@SuppressLint("NewApi")
private class ChoiceDragListener implements OnDragListener 

    @Override
    public boolean onDrag(View v, DragEvent event) 
        switch (event.getAction()) 
        case DragEvent.ACTION_DRAG_STARTED:
            //no action necessary
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            //no action necessary
            Toast.makeText(picture_to_word_24_color.this, "ACTION_DRAG_ENTERED", Toast.LENGTH_SHORT).show();
            break;
        case DragEvent.ACTION_DRAG_EXITED:        
            //no action necessary
            Toast.makeText(picture_to_word_24_color.this, "ACTION_DRAG_EXITED", Toast.LENGTH_SHORT).show();
            break;
        case DragEvent.ACTION_DROP:
            
            Toast.makeText(picture_to_word_24_color.this, "ACTION_DROP", Toast.LENGTH_SHORT).show();
            //handle the dragged view being dropped over a drop view
            View view = (View) event.getLocalState();
            //stop displaying the view where it was before it was dragged
            view.setVisibility(View.INVISIBLE);
            //view dragged item is being dropped on
            TextView dropTarget = (TextView) v;
            //view being dragged and dropped
            TextView dropped = (TextView) view;
            //update the text in the target view to reflect the data being dropped
            dropTarget.setText(dropped.getText());
            //make it bold to highlight the fact that an item has been dropped
            dropTarget.setTypeface(Typeface.DEFAULT_BOLD);
            //if an item has already been dropped here, there will be a tag
            Object tag = dropTarget.getTag();
            //if there is already an item here, set it back visible in its original place
            if(tag!=null)
            
                //the tag is the view id already dropped here
                int existingID = (Integer)tag;
                //set the original view visible again
                findViewById(existingID).setVisibility(View.VISIBLE);
            
            //set the tag in the target view being dropped on - to the ID of the view being dropped
            dropTarget.setTag(dropped.getId());
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            //no action necessary
            Toast.makeText(picture_to_word_24_color.this, "ACTION_DRAG_ENDED", Toast.LENGTH_SHORT).show();
            break;
        default:
            break;
        
        return true;
    
 

【问题讨论】:

你有什么问题请详细说明! 【参考方案1】:

尝试以下代码,它应该根据您在问题中的描述工作。 我添加了一个额外的东西,即我认为有必要的重置按钮。

picture_to_word_24_color.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical"
android:padding="10dp"
android:paddingLeft="50dp"
android:paddingRight="50dp" >


<TextView
android:id="@+id/option_1"
android:layout_
android:layout_
android:layout_margin="5dp"
android:background="@drawable/option"
android:gravity="center"
android:text="Apple"
android:textStyle="bold" />

<TextView
android:id="@+id/option_2"
android:layout_
android:layout_
android:layout_margin="5dp"
android:background="@drawable/option"
android:gravity="center"
android:text="Orange"
android:textStyle="bold" />

<TextView
android:id="@+id/option_3"
android:layout_
android:layout_
android:layout_margin="5dp"
android:background="@drawable/option"
android:gravity="center"
android:text="Ball"
android:textStyle="bold" />

<TextView
android:id="@+id/choice_1"
android:layout_
android:layout_
android:layout_margin="5dp"
android:background="@drawable/choice"
android:gravity="center"
android:text="A for " />

<TextView
android:id="@+id/choice_2"
android:layout_
android:layout_
android:layout_margin="5dp"
android:background="@drawable/choice"
android:gravity="center"
android:text="O for " />

<TextView
android:id="@+id/choice_3"
android:layout_
android:layout_
android:layout_margin="5dp"
android:background="@drawable/choice"
android:gravity="center"
android:text="B for " />

<Button 
android:layout_
android:layout_
android:text="Reset"
android:onClick="reset"/>

</LinearLayout>

Picture_to_word_24_color.java

package com.example.touchanddrag;

import android.os.Build;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.graphics.Typeface;
import android.view.DragEvent;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.widget.TextView;
import android.widget.Toast;

@SuppressLint("NewApi")
public class Picture_to_word_24_color extends Activity 

private TextView option1, option2, option3, choice1, choice2, choice3;
public CharSequence dragData;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.picture_to_word_24_color);

    //get both sets of text views

    //views to drag
    option1 = (TextView)findViewById(R.id.option_1);
    option2 = (TextView)findViewById(R.id.option_2);
    option3 = (TextView)findViewById(R.id.option_3);

    //views to drop onto
    choice1 = (TextView)findViewById(R.id.choice_1);
    choice2 = (TextView)findViewById(R.id.choice_2);
    choice3 = (TextView)findViewById(R.id.choice_3);

    //set touch listeners
    option1.setOnTouchListener(new ChoiceTouchListener());
    option2.setOnTouchListener(new ChoiceTouchListener());
    option3.setOnTouchListener(new ChoiceTouchListener());

    //set drag listeners
    choice1.setOnDragListener(new ChoiceDragListener());
    choice2.setOnDragListener(new ChoiceDragListener());
    choice3.setOnDragListener(new ChoiceDragListener());


/**
 * ChoiceTouchListener will handle touch events on draggable views
 *
 */
private final class ChoiceTouchListener implements OnTouchListener 
    @SuppressLint("NewApi")
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) 
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) 
            /*
             * Drag details: we only need default behavior
             * - clip data could be set to pass data as part of drag
             * - shadow can be tailored
             */
            ClipData data = ClipData.newPlainText("", "");
            DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
            //start dragging the item touched
            view.startDrag(data, shadowBuilder, view, 0);
            return true;
         else 
            return false;
        
    
 

/**
 * DragListener will handle dragged views being dropped on the drop area
 * - only the drop action will have processing added to it as we are not
 * - amending the default behavior for other parts of the drag process
 *
 */
@SuppressLint("NewApi")
private class ChoiceDragListener implements OnDragListener 

    @Override
    public boolean onDrag(View v, DragEvent event) 
        switch (event.getAction()) 
        case DragEvent.ACTION_DRAG_STARTED:
            //no action necessary
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            //no action necessary
            break;
        case DragEvent.ACTION_DRAG_EXITED:        
            //no action necessary
            break;
        case DragEvent.ACTION_DROP:

            //handle the dragged view being dropped over a drop view
            View view = (View) event.getLocalState();
            //view dragged item is being dropped on
            TextView dropTarget = (TextView) v;
            //view being dragged and dropped
            TextView dropped = (TextView) view;
            //checking whether first character of dropTarget equals first character of dropped
            if(dropTarget.getText().toString().charAt(0) == dropped.getText().toString().charAt(0))
            
                //stop displaying the view where it was before it was dragged
                view.setVisibility(View.INVISIBLE);
                //update the text in the target view to reflect the data being dropped
                dropTarget.setText(dropTarget.getText().toString() + dropped.getText().toString());
                //make it bold to highlight the fact that an item has been dropped
                dropTarget.setTypeface(Typeface.DEFAULT_BOLD);
                //if an item has already been dropped here, there will be a tag
                Object tag = dropTarget.getTag();
                //if there is already an item here, set it back visible in its original place
                if(tag!=null)
                
                    //the tag is the view id already dropped here
                    int existingID = (Integer)tag;
                    //set the original view visible again
                    findViewById(existingID).setVisibility(View.VISIBLE);
                
                //set the tag in the target view being dropped on - to the ID of the view being dropped
                dropTarget.setTag(dropped.getId());
                //remove setOnDragListener by setting OnDragListener to null, so that no further drag & dropping on this TextView can be done
                dropTarget.setOnDragListener(null);
            
            else
                //displays message if first character of dropTarget is not equal to first character of dropped
                Toast.makeText(Picture_to_word_24_color.this, dropTarget.getText().toString() + "is not " + dropped.getText().toString(), Toast.LENGTH_LONG).show();
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            //no action necessary
            break;
        default:
            break;
        
        return true;
    
 

public void reset(View view)

    option1.setVisibility(TextView.VISIBLE);
    option2.setVisibility(TextView.VISIBLE);
    option3.setVisibility(TextView.VISIBLE);

    choice1.setText("A for ");
    choice2.setText("O for ");
    choice3.setText("B for ");

    choice1.setTag(null);
    choice2.setTag(null);
    choice3.setTag(null);

    choice1.setTypeface(Typeface.DEFAULT);
    choice2.setTypeface(Typeface.DEFAULT);
    choice3.setTypeface(Typeface.DEFAULT);

    choice1.setOnDragListener(new ChoiceDragListener());
    choice2.setOnDragListener(new ChoiceDragListener());
    choice3.setOnDragListener(new ChoiceDragListener());


@Override
public boolean onCreateOptionsMenu(Menu menu) 
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.picture_to_word_24_color, menu);
    return true;



不要忘记检查目标 API 级别。因为我必须添加@SuppressLint("NewApi")

【讨论】:

亲爱的 Osama Mohammed Shai,我真的不知道该怎么说谢谢...我想说一百万谢谢你的帮助。你的代码是我真正需要的。如果我能给你一百张支票,我会的。再次感谢奥萨马。 嗨 Osama Mahammed,根据上面的代码,我们如何检测所有拖动对象何时结束?我的意思是,在我们已经将所有(Apple、Orage、Ball)拖到放置的目标之后,我需要完成这项工作。 如果您有更多问题,请在新问题中提出。我会尝试在那里回答。 谢谢Osama Mohammed Shaikh :)

以上是关于如何将 TextView 拖到正确的目标其他 TextView的主要内容,如果未能解决你的问题,请参考以下文章

如何让textview中的文字竖着显示

如何以编程方式添加TextView并在布局中对齐它们

如何从SharedPreferences文件中正确地将文本附加到TextView而不是覆盖它?

自定义视图中相对布局内的文本视图未正确应用重力?

UITableView - 如何识别我是不是将一个单元格拖到一个单元格上?

根据字符设置 TextView 的宽度