问题描述
我想要达到的目标:
我想在 Android 中创建拖放功能.我想使用特定布局(不同于被拖动对象本身)作为拖动阴影.
I want to create a drag and drop functionality in Android. I'd like to use a specific layout (different from the dragged object itself) as a drag shadow.
我得到了什么结果:
我的两种方法都没有按预期工作 - 我最终没有可见的拖动阴影(尽管目标确实收到了拖放).
Neither of my approaches works as expected - I end up with no visible drag shadow at all (although the target does receive the drop).
我尝试了什么:
我试过了
- 在活动中扩展
drag_item
布局,然后将其作为参数传递给影子构建器的构造函数
- inflating the
drag_item
layout in the activity, then passing it as an argument to the shadow builder's constructor
和
- 在阴影生成器的
onDrawShadow
方法中扩展drag_item
布局,然后在canvas
上绘制它
- inflating the
drag_item
layout in the shadow builder'sonDrawShadow
method, then drawing it on thecanvas
布局:
我的活动布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.app.DragDropTestActivity"
tools:ignore="MergeRootFrame">
<TextView
android:id="@+id/tvReceiver"
android:text="Drop here"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btnDragged"
android:layout_height="wrap_content"
android:text="Drag me"
android:layout_width="match_parent"/>
</LinearLayout>
我想用作拖影的布局:
dragged_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dragged Item"/>
</LinearLayout>
源代码:
这是两种方法的代码(分别由 1
、BuilderOne
和 2
、BuilderTwo
表示):
Here's the code with both approaches (represented by 1
, BuilderOne
and 2
, BuilderTwo
, respectively):
package com.example.app;
import android.graphics.Canvas;
import android.graphics.Point;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
public class DragDropTestActivity extends ActionBarActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drag_drop_test);
Button dragged = (Button) findViewById(R.id.btnDragged);
dragged.setOnTouchListener(
new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
LayoutInflater inflater = getLayoutInflater();
int approach = 1;
// both approaches fail
switch (approach) {
case 1: {
View draggedItem = inflater.inflate(R.layout.dragged_item, null);
BuilderOne builder = new BuilderOne(draggedItem);
v.startDrag(null, builder, null, 0);
break;
}
case 2: {
BuilderTwo builder = new BuilderTwo(inflater, v);
v.startDrag(null, builder, null, 0);
break;
}
}
return true;
}
});
}
我的 BuilderOne
类:
public static class BuilderOne extends View.DragShadowBuilder
{
public BuilderOne(View view)
{
super(view);
}
@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
{
super.onProvideShadowMetrics(
shadowSize,
shadowTouchPoint);
}
}
和BuilderTwo
类:
public static class BuilderTwo extends View.DragShadowBuilder
{
final LayoutInflater inflater;
public BuilderTwo(LayoutInflater inflater, View view)
{
super(view);
this.inflater = inflater;
}
@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint)
{
super.onProvideShadowMetrics(
shadowSize,
shadowTouchPoint);
}
@Override
public void onDrawShadow(Canvas canvas)
{
final View draggedItem = inflater.inflate(R.layout.dragged_item, null);
if (draggedItem != null) {
draggedItem.draw(canvas);
}
}
}
}
问题:
我做错了什么?
更新:
已添加赏金.
推荐答案
Kurty 是正确的,在这种情况下您不需要继承 DragShadowBuilder
.我的想法是,您传递给 DragShadowBuilder
的视图实际上并不存在于布局中,因此它不会呈现.
Kurty is correct in that you shouldn't need to subclass DragShadowBuilder
in this case. My thought is that the view you're passing to the DragShadowBuilder
doesn't actually exist in the layout, and therefore it doesn't render.
与其将 null
作为第二个参数传递给 inflater.inflate
,不如尝试将膨胀的 View
实际添加到层次结构的某个位置,然后将其传递给常规 DragShadowBuilder
:
Rather than passing null
as the second argument to inflater.inflate
, try actually adding the inflated View
to the hierarchy somewhere, and then passing it to a regular DragShadowBuilder
:
View dragView = findViewById(R.id.dragged_item);
mDragShadowBuilder = new DragShadowBuilder(dragView);
v.startDrag(null, mDragShadowBuilder, null, 0);
编辑
我知道让 dragged_item
视图一直呈现并不是您想要的,但如果它有效,那么至少我们知道问题出在哪里并且可以寻找解决方案改为那个!
I'm aware that having the dragged_item
view being rendered all the time isn't what you want, but if it works then at least we know where the problem is and can look for a solution to that instead!
这篇关于如何创建自定义拖动阴影?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!