您的位置:首页 > 移动开发 > Android开发

Android Api Demos登顶之路(106)View-->DragAndDrop

2015-10-21 20:28 375 查看
这个demo演示了拖放功能的实现

同样使用了自定义属性和自定义视图

自定义属性:attr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DraggableDot">
<attr name="radius" format="dimension"/>
<attr name="legend" format="string"/>
<attr name="anr">
<enum name="none" value="0"/>
<enum name="thumbnail" value="1"/>
<enum name="drop" value="2"/>
</attr>

</declare-styleable>
</resources>


DraggableDot.java

/*定制一个自定义的视图组件*/
public class DraggableDot extends View {
private static final String TAG = "DraggableDot";

// 是否处于拖动的状态
private boolean mDragInProgress;
// 拖拽阴影是否进入当前View(即当前View是否接收到了拖动进入的事件)
private boolean mHovering;
// view是否接受拖放事件
private boolean mAcceptsDrag;
// 用于显示拖动的数据
private TextView mReportTextView;

private Paint mPaint;
private Paint mLegendPaint;
private Paint mGlow;

private static final int NUM_GLOW_STEPS = 10;
private static final int GREEN_STEP = 0x0000FF00 / NUM_GLOW_STEPS;
private static final int WHITE_STEP = 0x00FFFFFF / NUM_GLOW_STEPS;
private static final int ALPHA_STEP = 0xFF000000 / NUM_GLOW_STEPS;

private int mRadius;
private int mAnrType;
private CharSequence mLegend;

private static final int ANR_SHADOW = 1;
private static final int ANR_DROP = 2;

private void sleepSixSecond() {
// 获取自系统启动至当前的时间,不包括系统休眠的时间
long start = SystemClock.uptimeMillis();
do {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (SystemClock.uptimeMillis() < start + 6000);
}

// 绘制拖拽阴影的类
private class ANRShadowBuilder extends DragShadowBuilder {
boolean mDoAnr;

public ANRShadowBuilder(View view, boolean doAnr) {
super(view);
mDoAnr = doAnr;
}

// 绘制阴影
@Override
public void onDrawShadow(Canvas canvas) {
if (mDoAnr) {
sleepSixSecond();
}
super.onDrawShadow(canvas);
}
}

public DraggableDot(Context context, AttributeSet attrs) {
//必须调用这个构造方法,不能调用super(context);
super(context,attrs);
setFocusable(true);
setClickable(true);

mLegend = "";

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStrokeWidth(6);
mPaint.setColor(0xffd00000);

mLegendPaint = new Paint();
mLegendPaint.setAntiAlias(true);
mLegendPaint.setTextAlign(Paint.Align.CENTER);
mLegendPaint.setColor(0xfff0f0ff);

mGlow = new Paint();
mGlow.setAntiAlias(true);
mGlow.setStrokeWidth(1);
mGlow.setStyle(Paint.Style.STROKE);

TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.DraggableDot);
int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
// 遍历所有自定义的属性
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.DraggableDot_radius:
// 获取某个dimension的值,无论单位是dp、sp或px都会乘以density
mRadius = a.getDimensionPixelSize(attr, 0);
break;
case R.styleable.DraggableDot_legend:
mLegend = a.getText(attr);
break;
case R.styleable.DraggableDot_anr:
mAnrType = a.getInt(attr, 0);
break;
}
}
a.recycle();

setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// 定义拖动数据,为普通的文本类型
ClipData data = ClipData.newPlainText("dot",
"Dot:" + v.toString());
/*
* 开启拖动
* 第二个参数表示如果anr的类型为thumbnail(一小会儿),则让程序在6秒内无响应(休眠6秒)
* 则无法完成阴影的绘制,该View不会响应拖动事件
* 第三个参数表示包含一些关于拖放操作数据的对象,在拖动过程中被系统发送到每一个拖放事件中
*/
v.startDrag(data, new ANRShadowBuilder(v,
mAnrType == ANR_SHADOW), (Object) v, 0);
return true;
}
});

}

public void setReportView(TextView view) {
mReportTextView = view;
}

@Override
protected void onDraw(Canvas canvas) {
float wf = getWidth();
float hf = getHeight();
//System.out.println(wf);
final float cx = wf / 2;
final float cy = hf / 2;
wf -= getPaddingLeft() + getPaddingRight();
hf -= getPaddingTop() + getPaddingBottom();
float rad = (wf < hf) ? wf / 2 : hf / 2;
canvas.drawCircle(cx, cy, rad, mPaint);

// 绘制文本
if (mLegend != null && mLegend.length() > 0) {
canvas.drawText(mLegend, 0, mLegend.length(), cx,
cy + mLegendPaint.getFontSpacing() / 2, mLegendPaint);
}

if (mDragInProgress && mAcceptsDrag) {
for (int i = NUM_GLOW_STEPS; i > 0; i--) {
// 当拖拽影子退出当前view时圆环为绿、白、红的渐变色;
// 当拖拽影子退出当前view时圆环为白的渐变色;
int color = (mHovering) ? WHITE_STEP : GREEN_STEP;
color = i * (color | ALPHA_STEP);
mGlow.setColor(color);
canvas.drawCircle(cx, cy, rad, mGlow);
rad -= 0.5f;
canvas.drawCircle(cx, cy, rad, mGlow);
rad -= 0.5f;
}
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//System.out.println(getPaddingLeft());
//计算视图的宽和高
int totalDiameter=2*mRadius+getPaddingLeft()+getPaddingRight();
//System.out.println(totalDiameter);
setMeasuredDimension(totalDiameter, totalDiameter);

}

@Override
public boolean onDragEvent(DragEvent event) {
boolean result=false;
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
Log.i(TAG, "Drag started, event=" + event);
mDragInProgress=true;
mAcceptsDrag=true;
result=true;
invalidate();
break;
case DragEvent.ACTION_DRAG_ENDED:
Log.i(TAG, "Drag ended");
if(mAcceptsDrag){
invalidate();
}
mDragInProgress=false;
mHovering=false;
break;
case DragEvent.ACTION_DRAG_LOCATION:
//当View对象收到一个ACTION_DRAG_ENTERED事件之后,并且拖拽影子依然还在这个
//对象的边框之内时,这个View对象的拖拽事件监听器会接收这种事件操作类型
Log.i(TAG, "... seeing drag locations ..." );
result=mAcceptsDrag;
break;
case DragEvent.ACTION_DROP:
//当View对象收到一个ACTION_DRAG_ENTERED事件之后,并且拖拽影子依然还在这个
//对象的边框之内时,这个View对象的拖拽事件监听器会接收这种事件操作类型
Log.i(TAG, "Got a drop! dot=" + this + " event=" + event );
if(mAnrType==ANR_DROP){
sleepSixSecond();
}
processDrop(event);
result=true;
break;
case DragEvent.ACTION_DRAG_ENTERED:
Log.i(TAG, "Entered dot @ " + this );
mHovering=true;
invalidate();
break;
case DragEvent.ACTION_DRAG_EXITED:
Log.i(TAG, "Exited dot @ " + this );
mHovering=false;
invalidate();
break;

default:
Log.i(TAG, "other drag event: " + event);
result=mAcceptsDrag;
break;
}
return result;
}

private void processDrop(DragEvent event) {
ClipData data=event.getClipData();
//获取剪贴板中条目的数量
int N=data.getItemCount();
for(int i=0;i<N;i++){
ClipData.Item item=data.getItemAt(i);
Log.i(TAG, "Dropped item " + i + " : " + item);
if(mReportTextView!=null){
//将条目的数据强制转化为文本
String text=item.coerceToText(getContext()).toString();
//如果拖动后在自己上面释放
if(event.getLocalState()==(Object)this){
text+=" : Dropped on self!";
}
mReportTextView.setText(text);
}
}
}

}


activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dot="http://schemas.android.com/apk/res/com.fisthosky.draggabledot"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical" >

<TextView
android:id="@+id/result_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#ffffffff"
/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<com.fisthosky.draganddrop.DraggableDot
android:id="@+id/dot1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
dot:radius="64dp" />

<com.fisthosky.draganddrop.DraggableDot
android:id="@+id/drag_dot2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
dot:anr="thumbnail"
android:padding="15dp"
dot:legend="Drag ANR"
dot:radius="64dp" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<com.fisthosky.draganddrop.DraggableDot
android:id="@+id/drag_dot3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
dot:radius="64dp"
dot:legend="Drop ANR"
dot:anr= "drop"/>

<com.fisthosky.draganddrop.DraggableDot
android:id="@+id/drag_drag_hidden"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
dot:radius="64dp"
dot:legend="Surprise"
android:visibility="invisible"/>
</LinearLayout>
<TextView android:id="@+id/drag_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:textColor="#ffffff"/>

</LinearLayout>


MainActivity

public class MainActivity extends Activity {
private TextView mResultText;
private DraggableDot mDragHidden;

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

TextView textView=(TextView) findViewById(R.id.drag_text);

DraggableDot dot;
dot=(DraggableDot) findViewById(R.id.dot1);
dot.setReportView(textView);
dot=(DraggableDot) findViewById(R.id.drag_dot2);
dot.setReportView(textView);
dot=(DraggableDot) findViewById(R.id.drag_dot3);
dot.setReportView(textView);

mDragHidden=(DraggableDot) findViewById(R.id.drag_drag_hidden);
mDragHidden.setReportView(textView);

mResultText=(TextView) findViewById(R.id.result_text);
//当拖放启动时系统会将拖放事件发送至每个view
mResultText.setOnDragListener(new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
int aciton=event.getAction();
switch (aciton) {
case DragEvent.ACTION_DRAG_STARTED:
mDragHidden.setVisibility(View.VISIBLE);
break;
case DragEvent.ACTION_DRAG_ENDED:
mDragHidden.setVisibility(View.INVISIBLE);
boolean dropped=event.getResult();
mResultText.setText(dropped ? "Dropped!" : "No drop");
break;

default:
break;
}
return false;
}
});
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: