如何将 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的主要内容,如果未能解决你的问题,请参考以下文章
如何从SharedPreferences文件中正确地将文本附加到TextView而不是覆盖它?