2011-11-22 84 views
0

我開始認爲缺乏OpenGL我不能拖動一個簡單的視圖。說真的,我已經閱讀了10-15個教程來拖拽視圖,並且每個教程都會向您展示如何將drawable拖拽到視圖中,或者拖拽imageview中的圖像(通過矩陣轉換)。但是沒有任何教程告訴你如何在超級視圖中拖動一個簡單的視圖。它真的很簡單。我有一個超級視圖,我添加可以說10個子視圖。無論我的手指觸碰到什麼,我爲iOS http://www.facebook.com/MakeASnowman製作了一個應用程序(任何一天都會點擊應用商店),並試圖爲Android構建它。但是沒有簡單的方法來做iOS中那麼簡單的事情(雙指旋轉,拖動視圖等)。這就是我想要的:我有一個自定義視圖,可以在其畫布上繪製圖像。然後,我將這些自定義視圖中的一個或多個實例化到「超級視圖」上。我可以拖拽/操作這些視圖(意思是我不翻譯這些視圖中的可繪畫,而是實際的視圖本身)。Android在一個超級視圖上拖動很多視圖

這裏是我的代碼,有正確的操作,但它執行視圖中繪製的他們:

package com.spentaklabs.view; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
import android.view.View; 


public class MAView extends View 
{ 
Drawable image; 
private String imgName; 
private float mPosX; 
private float mPosY; 

private float mLastTouchX; 
private float mLastTouchY; 

private static final int INVALID_POINTER_ID = -1; 
private int mActivePointerId = INVALID_POINTER_ID; 

private ScaleGestureDetector mScaleDetector; 

private float mScaleFactor = 1.f; 

public MAView(Context context) 
{ 
    super(context); 
} 

public MAView(Context context,String imgName) 
{ 
    this(context); 
    this.imgName = imgName; 
    image = context.getResources().getDrawable(R.drawable.hatshairears0); 
    image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight()); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
} 

public MAView(Context context, AttributeSet attrs, int defStyle) 
{ 
    super(context,attrs,defStyle); 
} 

@Override 
public void onDraw(Canvas canvas) 
{ 
    canvas.save(); 
    canvas.translate(mPosX, mPosY); 
    canvas.scale(mScaleFactor, mScaleFactor); 
    image.draw(canvas); 
    canvas.restore(); 
} 

@Override 
public boolean onTouchEvent(MotionEvent ev) 
{ 
    mScaleDetector.onTouchEvent(ev); 

    final int action = ev.getAction(); 

    switch (action) 
    { 
     case MotionEvent.ACTION_DOWN: 
     { 
      final float x = ev.getX(); 
      final float y = ev.getY(); 

      mLastTouchX = x; 
      mLastTouchY = y; 

      mActivePointerId = ev.getPointerId(0); 
      break; 
     } 

     case MotionEvent.ACTION_MOVE: 
     { 
      final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
      final float x = ev.getX(pointerIndex); 
      final float y = ev.getY(pointerIndex); 

     // Only move if the ScaleGestureDetector isn't processing a gesture. 
      if (!mScaleDetector.isInProgress()) { 
       final float dx = x - mLastTouchX; 
       final float dy = y - mLastTouchY; 

       mPosX += dx; 
       mPosY += dy; 

       invalidate(); 
      } 

      mLastTouchX = x; 
      mLastTouchY = y; 

      break; 

     } 

     case MotionEvent.ACTION_UP: 
     { 
      mActivePointerId = INVALID_POINTER_ID; 
      break; 
     } 

     case MotionEvent.ACTION_CANCEL: 
     { 
      mActivePointerId = INVALID_POINTER_ID; 
      break; 
     } 

     case MotionEvent.ACTION_POINTER_UP: 
     { 
      // Extract the index of the pointer that left the touch sensor 
      final int pointerIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; 
      final int pointerId = ev.getPointerId(pointerIndex); 

      if (pointerId == mActivePointerId) 
      { 
       // This was our active pointer going up. Choose a new 
       // active pointer and adjust accordingly. 
       final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
       mLastTouchX = ev.getX(newPointerIndex); 
       mLastTouchY = ev.getY(newPointerIndex); 
       mActivePointerId = ev.getPointerId(newPointerIndex); 
      } 
      break; 
     } 
    } 
    return true; 
} 


private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     mScaleFactor *= detector.getScaleFactor(); 

     // Don't let the object get too small or too large. 
     mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); 

     invalidate(); 
     return true; 
    } 
} 

} 

回答

3

下面是一些代碼,將讓您拖動查看任何你想要在屏幕上。 ..

package com.matthieu; 

import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.Rect; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.widget.FrameLayout.LayoutParams; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.*; 

import java.util.ArrayList; 
import java.util.Arrays; 

public class DragActivity extends Activity implements View.OnTouchListener, AdapterView.OnItemLongClickListener 
{ 
    private static final String TAG="DragActivity"; 

    private static final int NOT_DRAGGING = 0; 
    private static final int DRAGGING = 1; 

    private int state=NOT_DRAGGING; 
    private ImageView draggable =null; 
    private int dragged_position; 

    float current_x, current_y; 
    int current_icon = R.drawable.notepad; 

    private ArrayList<String> names = new ArrayList<String>(Arrays.asList("Matt", "Xiaohui", "Yong", "Hunt", "Andy", "Ivy", "Guanglong", "Zeyan", "Yanxia", 
      "Chris", "Mark", "Matthieu")); 
    private ArrayList<Integer> icons = new ArrayList<Integer>(Arrays.asList(R.drawable.glasses, R.drawable.monkey, R.drawable.normal, R.drawable.smile, R.drawable.wink)); 
    private ArrayList<Integer> matching; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     setupListContent(); 

     ListView list = (ListView) findViewById(R.id.main_list); 
     list.setAdapter(new DragListAdapter()); 
     list.setOnItemLongClickListener(this); 

     list.setOnTouchListener(this); 

     ImageView image = (ImageView) findViewById(R.id.main_image); 
     image.setImageResource(current_icon); 
    } 

    private void setupListContent() { 
     matching = new ArrayList<Integer>(); 
     for (int i=0; i<names.size(); i++) { 
      matching.add((int) (icons.size() * Math.random())); 
     } 
    } 

    @SuppressWarnings("unchecked") 
    private class DragListAdapter extends ArrayAdapter { 
     public DragListAdapter() { 
      super(DragActivity.this, R.layout.list_item, names); 

     } 

     public View getView(int position, View convertView, ViewGroup parent) { 
      View row = convertView; 
      if (row == null) { 
       LayoutInflater inflater = getLayoutInflater(); 
       row = inflater.inflate(R.layout.list_item, parent, false); 
      } 

      row.setDrawingCacheEnabled(true); 
      TextView name = (TextView) row.findViewById(R.id.item_text); 
      ImageView icon = (ImageView) row.findViewById(R.id.item_icon); 

      name.setText(names.get(position)); 
      icon.setImageResource(icons.get(matching.get(position))); 

      return row; 
     } 
    } 

    private boolean checkOnDropIcon(MotionEvent me) { 
     ImageView drop_icon = (ImageView) findViewById(R.id.main_image); 
     Rect icon_rect = new Rect(); 
     drop_icon.getGlobalVisibleRect(icon_rect); 
     Log.d(TAG, "icon at " + icon_rect.left + "<- ->" + icon_rect.right + ", " + 
       icon_rect.top + "^v" + icon_rect.bottom); 
     if ((me.getRawX()<icon_rect.left) || (me.getRawX()>icon_rect.right) || 
       (me.getRawY()<icon_rect.top) || (me.getRawY()>icon_rect.bottom)) { 
      return false; 
     } 
     else { 
      return true; 
     } 
    } 

    private void checkOnDrop(MotionEvent me) { 
     boolean onDropIcon = checkOnDropIcon(me); 
     ImageView image = (ImageView) findViewById(R.id.main_image); 
     if ((onDropIcon) && (current_icon==R.drawable.notepad)) { 
      current_icon = R.drawable.exit; 
      image.setImageResource(current_icon); 
      image.invalidate(); 
      return; 
     } 
     if ((!onDropIcon) && (current_icon==R.drawable.exit)) { 
      current_icon = R.drawable.notepad; 
      image.setImageResource(current_icon); 
      image.invalidate(); 
      return; 
     } 
    } 

    public boolean onTouch(View view, MotionEvent me) { 
     if (state == NOT_DRAGGING) { 
      // get the position of the touch so we know where to place the dragging item if it is a long press 
      current_x = me.getRawX(); 
      current_y = me.getRawY(); 
      return false; 
     } 
     else { 
      FrameLayout frame = (FrameLayout) findViewById(R.id.drag_space); 

      if (me.getAction()==MotionEvent.ACTION_UP) { 
       frame.removeAllViews(); 
       draggable=null; 
       frame.setVisibility(View.GONE); 
       state=NOT_DRAGGING; 

       // check if we dropped a name 
       if (checkOnDropIcon(me)) { 
        names.remove(dragged_position); 
        matching.remove(dragged_position); 

        ListView list = (ListView) findViewById(R.id.main_list); 
        DragListAdapter adapter = (DragListAdapter) list.getAdapter(); 
        adapter.notifyDataSetChanged(); 
       } 

       // restore the icon 
       ImageView image = (ImageView) findViewById(R.id.main_image); 

       current_icon = R.drawable.notepad; 
       image.setImageResource(current_icon); 
       image.invalidate(); 
      } 
      if (me.getAction()==MotionEvent.ACTION_MOVE) { 
       int frame_position[] = new int[2]; 
       frame.getLocationOnScreen(frame_position); 

       draggable.setPadding(
         (int) me.getRawX()-frame_position[0]-(draggable.getDrawable().getIntrinsicWidth()/2), 
         (int) me.getRawY()-frame_position[1]-(draggable.getDrawable().getIntrinsicHeight()/2), 
         0, 0); 
       draggable.invalidate(); 

       checkOnDrop(me); 
      } 

      return true; 
     } 
    } 

    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { 
     if (state == DRAGGING) { 
      Log.d(TAG, "already have an object moving... ?"); 
      return false; 
     } 

     FrameLayout frame = (FrameLayout) findViewById(R.id.drag_space); 
     int frame_position[] = new int[2]; 
     frame.getLocationOnScreen(frame_position); 

     // setup everything for dragging 
     state = DRAGGING; 
     dragged_position = i; 

     draggable = new ImageView(this); 
     Bitmap bm = view.getDrawingCache(); 
     draggable.setImageBitmap(bm); 
     draggable.setAlpha(150); 
     draggable.setScaleType(ImageView.ScaleType.CENTER); 
     draggable.setDrawingCacheEnabled(true); 
     draggable.setPadding((int) current_x-frame_position[0]-(bm.getWidth()/2), (int) current_y-frame_position[1]-(bm.getHeight()/2), 0, 0); 

     frame.setVisibility(View.VISIBLE); 
     frame.addView(draggable, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); 

     return true; 
    } 
} 

下面是main.xml中:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/main_frame" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent"> 
    <LinearLayout 
      android:orientation="vertical" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      > 
     <ListView 
       android:id="@+id/main_list" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:layout_weight="1" 
       /> 
     <ImageView 
       android:id="@+id/main_image" 
       android:layout_width="fill_parent" 
       android:layout_height="32sp" 
       /> 
    </LinearLayout> 
    <FrameLayout 
      android:id="@+id/drag_space" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:visibility="gone"/> 
</FrameLayout> 

而且list_i tem.xml

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="fill_parent" 
       android:layout_height="fill_parent" 
       android:orientation="horizontal"> 
    <ImageView 
      android:id="@+id/item_icon" 
      android:layout_height="wrap_content" 
      android:layout_width="wrap_content" 
      android:layout_margin="3sp"/> 
    <TextView 
      android:id="@+id/item_text" 
      android:layout_height="wrap_content" 
      android:layout_width="fill_parent" 
      android:layout_weight="1"/> 
</LinearLayout> 

希望有幫助。

+0

我很想嘗試一下。在你的例子中,你僅僅使用一個列表來保存正在實例化的項目? – spentak

+0

正確,您可以拖動這些項目。我只是把一張圖片和一些文本放在那裏,以確保它能正常工作... – Matthieu

+0

我把apk放在那裏:http://dl.dropbox.com/u/44437318/DragActivity-debug.apk所以你可以試試它看看它是否做你期望 – Matthieu

相關問題