2011-10-25 42 views
1

我想修改TouchListView組件,以允許我將一個項目從列表視圖拖到另一個視圖上,以創建拖放選擇系統。用戶將拖動一個列表項並釋放它以指示選擇。修改TouchList視圖從列表拖動到另一個視圖(圖像視圖)

到目前爲止,我已經修改DropListener類的onDrop方法以傳遞MotionEvent。我甚至使用運動的getY()方法來確定用戶是否放棄了圖像視圖上的拖動視圖。我正在使用getY()的原始值,如果它小於-50,我接受該值爲有效的下降。

但我擔心,這是一個相當不靈活的解決方案,並且容易出錯。有沒有更好的方法來確定用戶何時釋放目標視圖區域?有沒有我不能簡單地尋找負數的情況?是否有一種方法可以真正查看給定的一組X/Y座標下的視圖?

請注意佈局進行中的附圖。

enter image description here

+0

我從來沒有嘗試過這個,但每個小部件上的'getLocationInWindow()'應該爲您提供一組一致的座標進行比較。原則上,您可以結合使用'-50'來確定'-50'是否在您的目標小部件上。 – CommonsWare

+0

謝謝!那樣做了。在這種情況下,傳遞給DropListener和Drag listener中的MotionEvent引用時,我可以使交互非常好,包括在拖動視圖位於目標上時拖放目標突出顯示。 –

+0

很高興工作!如果您有一些示例代碼可以發送給我,我很樂意將其作爲'TouchListView'' README'的一部分編寫。 – CommonsWare

回答

1

這裏是我想出了工作的解決方案。

package com.commonsware.cwac.tlv.demo; 

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

import android.app.ListActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.ViewTreeObserver; 
import android.view.ViewTreeObserver.OnGlobalLayoutListener; 
import android.widget.ArrayAdapter; 
import android.widget.ImageView; 
import android.widget.TextView; 

import com.commonsware.cwac.tlv.TouchListView; 

public class TouchListViewDemo extends ListActivity { 
    private static String[] items={"lorem", "ipsum", "dolor", "sit", "amet", 
                    "consectetuer", "adipiscing", "elit", "morbi", "vel", 
                    "ligula", "vitae", "arcu", "aliquet", "mollis", 
                    "etiam", "vel", "erat", "placerat", "ante", 
                    "porttitor", "sodales", "pellentesque", "augue", "purus"}; 
    private TouchListView tlv; 
    private IconicAdapter adapter=null; 
    private ArrayList<String> array=new ArrayList<String>(Arrays.asList(items)); 

    private TextView target_name_display; 
    private ImageView target; 

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

     tlv = (TouchListView)getListView(); 
     adapter=new IconicAdapter(); 
     setListAdapter(adapter); 

     tlv.setDropListener(onDrop); 
     tlv.setRemoveListener(onRemove); 


     target = (ImageView) findViewById(R.id.drag_target_area); 
     target_name_display = (TextView) findViewById(R.id.name_text); 
     Log.d("TARGET", "Target:"+target); 
     Log.d("TARGET", "TargeName Displayt:"+target_name_display); 


     ViewTreeObserver vto = target.getViewTreeObserver(); 
     vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 

      @Override 
      public void onGlobalLayout() { 
       target.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
       int height = target.getHeight(); 
       int top = target.getTop(); 
       int tlv_y_position = tlv.getTop(); 
       Log.d("ON LAYOUT", "Height:"+ height+ " top:"+top+" tlv_y_position:"+tlv_y_position);    
      } 
     }); 

    } 

    private TouchListView.DropListener onDrop=new TouchListView.DropListener() { 
     @Override 
     public void drop(int from, int to, MotionEvent e) { 
      Log.i("TOUCH VIEW DEMO", "From: "+from + " TO: "+to); 
      Log.i("TOUCH VIEW DEMO", "Event: "+e.getY()); 
       String item=adapter.getItem(from); 

       // 
       int[] target_coords = new int[2]; 
       int[] tlv_coords = new int[2]; 
       target.getLocationInWindow(target_coords); 
       tlv.getLocationInWindow(tlv_coords); 
       int height = target.getMeasuredHeight(); 
       int negative_top = -1*(tlv_coords[1]-target_coords[1]); 
       Log.d("TOUCH VIEW DEMO", " negative_top:"+negative_top + " e.getY():"+e.getY() + " heigh:"+height); 
       Log.d("TOUCH VIEW DEMO", "Target Coords:"+ target_coords[0] +","+ target_coords[1]); 
       Log.d("TOUCH VIEW DEMO", "Tlv Coords:"+ tlv_coords[0] +","+ tlv_coords[1]); 
       if(e.getY() > negative_top && e.getY() < negative_top + height){ 
        target_name_display.setText(item.toString()); 
        adapter.remove(item); 
       } 
       //adapter.remove(item); 
       //adapter.insert(item, to); 
     } 
    }; 

    private TouchListView.RemoveListener onRemove=new TouchListView.RemoveListener() { 
     @Override 
     public void remove(int which) { 
       adapter.remove(adapter.getItem(which)); 
     } 
    }; 

    class IconicAdapter extends ArrayAdapter<String> { 
     IconicAdapter() { 
      super(TouchListViewDemo.this, R.layout.row2, array); 
     } 

     public View getView(int position, View convertView, 
               ViewGroup parent) { 
      View row=convertView; 

      if (row==null) {              
       LayoutInflater inflater=getLayoutInflater(); 

       row=inflater.inflate(R.layout.row2, parent, false); 
      } 

      TextView label=(TextView)row.findViewById(R.id.label); 

      label.setText(array.get(position)); 

      return(row); 
     } 
    } 
} 

該代碼包含了很多評論和varaibles每次計算,我將重構。但是您可以修改TouchListView演示以使其自行工作。

這是我使用的main.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="vertical" > 
    <RelativeLayout 
     android:id="@+id/drag_here_layout" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="15dp" 
     android:layout_marginRight="15dp" 
     android:layout_weight="1.0" 
     android:background="@drawable/matches_current_match_bg" 
     android:paddingBottom="30dp" > 

     <TextView 
      android:id="@+id/drag_here_text"    
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerHorizontal="true" 
      android:layout_marginBottom="5dp" 
      android:layout_marginTop="15dp" 
      android:text="DRAG HERE" 
      android:textSize="14dp" /> 

     <ImageView 
      android:id="@+id/drag_target_area" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:layout_below="@id/drag_here_text" 
      android:layout_marginBottom="15dp" 
      android:layout_marginLeft="15dp" 
      android:layout_marginRight="15dp" 
      android:background="#00000000" 
      android:scaleType="fitXY" 
      android:src="@drawable/match_drag_here_target" /> 
     <TextView 
      android:id="@+id/name_text"    
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerHorizontal="true" 
      android:layout_alignTop="@id/drag_target_area" 
      android:layout_marginBottom="5dp" 
      android:layout_marginTop="15dp" 
      android:text="" 
      android:textSize="14dp" /> 
    </RelativeLayout> 
<com.commonsware.cwac.tlv.TouchListView 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tlv="http://schemas.android.com/apk/res/com.commonsware.cwac.tlv.demo" 

    android:id="@android:id/list" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:drawSelectorOnTop="false" 
    tlv:normal_height="64dip" 
    tlv:grabber="@+id/icon" 
    tlv:remove_mode="slideRight" 
    android:layout_weight="1.0" 
/> 
</LinearLayout> 

再次感謝CommonsWare爲您的優秀TouchListView Widget

+0

我可能會在單獨的活動中將此添加到演示中並記錄該技術。謝謝! – CommonsWare

+0

實際上,它看起來像你必須修改'TouchListView'來完成這個工作,在''DropEvent''接口中添加'MotionEvent'的第三個參數。我仍然可以添加這個,但是我需要考慮如何最好地做到這一點,而不是破壞向後兼容性。我不能在界面上添加新的方法而不強制每個人都去執行它... – CommonsWare

+0

是的,我做到了。也許有一種方法來實現可選參數的接口?或者可能暴露另一個可以在現有偵聽器中調用的方法來獲取MotionEvent。另外,我注意到在github中,你將它列爲0.4.1版本 - 我認爲在1.0版本之前允許你自己進行一些界面變更是安全的,只要你給人們一些線索即可。 –