2013-07-24 56 views
3

我有一個網格視圖我在哪裏動態地添加按鈕。 我將OnTouch監聽器設置爲網格視圖。 我想要當我的手指在特定的單元格上移動,然後該單元格元素應該彈出 類似我們的Android鍵盤的方式。彈出gridview單元格ontouch

public class MainActivity extends Activity { 
private ArrayList<Integer> data; 
private GridView gv; 

private TextView biggerView = null; 

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

    createData(); 
    gv = (GridView) findViewById(R.id.grid); 
    gv.setNumColumns(10); 
    gv.setAdapter(new FilterButtonAdapter(data, this)); 

    gv.setOnTouchListener(new OnTouchListener() { 

     @Override 
     public boolean onTouch(View arg0, MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_MOVE) { 
       try { 
        int position = gv.pointToPosition((int) event.getX(), 
          (int) event.getY()); 

        View v = (View) gv.getChildAt(position); 
        if (v != null) { 
         gv.requestFocus(); 
          gv.setSelection(gv.pointToPosition((int) 
          event.getX(), (int) event.getY())); 

        } 

        return true; 
       } catch (Exception e) { 
        return true; 
       } 
      } 

      if (event.getAction() == MotionEvent.ACTION_UP) { 

       int position = gv.pointToPosition((int) event.getX(), 
         (int) event.getY()); 
       View v = (View) gv.getChildAt(position); 
       if (v != null) { 
        gv.clearFocus(); 
        TextView tv = (TextView) v.findViewById(R.id.texttoadd); 
        Toast.makeText(MainActivity.this, tv.getText(), 
          Toast.LENGTH_SHORT).show(); 

       } 

       return true; 
      } 
      return false; 
     } 
    }); 

} 

private void createData() { 
    data = new ArrayList<Integer>(); 
    for (int i = 0; i < 200; i++) { 
     data.add(i); 
    } 
} 


enter code here 

我有寫這個代碼是給我選擇的項目,但當項目較多則電網滾動,之後的我沒有得到我我選擇

項目I想通了的X和Y位置正在逐漸改變,當電網滾動 我可能是錯的

請幫助

+1

您可以檢查這個例子https://github.com/AlexStarc/MM5/tree/master/ MM5/src/com/sandrstar/android/gallery。 – sandrstar

+0

乾草感謝您的回覆。但我應該檢查哪一個 –

+1

您可以從ThumbnailsView開始。基本理念 - 做適當的動畫。 Jsut在4.2設備上再次檢查它,它仍然有效。 – sandrstar

回答

1

我認爲在觸摸位置檢測的問題中提出的建議可能無效,因爲獲得滾動位置的方法更多。

實施的主要觀點如下:

  1. 使用onScrollChanged()跟蹤滾動位置在每一個時刻;
  2. 以上面單獨的視圖顯示選擇GridView;
  3. 如果選中的項目可見,請跟蹤(使用this question);

因此,爲了獲得適當的滾動回調,小幅定製GridView需要:

public class ScrollAwareGridView extends GridView { 

    /** Callback interface to report immediate scroll changes */ 
    public interface ImmediateScrollListener { 
     void onImmediateScrollChanged(); 
    } 

    /** External listener for */ 
    private ImmediateScrollListener mScrollListener = null; 

    public ScrollAwareGridView(final Context context) { 
     super(context); 
    } 

    public ScrollAwareGridView(final Context context, final AttributeSet attrs) { 
     super(context, attrs); 
    } 

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

    @Override 
    protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt) { 
     super.onScrollChanged(l, t, oldl, oldt); 

     if (null != mScrollListener) { 
      mScrollListener.onImmediateScrollChanged(); 
     } 
    } 

    /** 
    * @param listener {@link ImmediateScrollListener} 
    */ 
    public void setImmediateScrollListener(final ImmediateScrollListener listener) { 
     mScrollListener = listener; 
    } 
} 

將放在XML通過以下方式(main.xml中):

<RelativeLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

    <com.example.TestApp.ScrollAwareGridView 
     android:id="@+id/grid" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:numColumns="3" /> 

    <!-- Selection view --> 
    <ImageView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:id="@+id/selectedImage" 
     android:visibility="gone" /> 
</RelativeLayout> 

在上面的xml中還提供了選擇視圖。

活動將處理項目的選擇(但是,爲了不在活動代碼中保留特定於網格的邏輯,保留選擇並滾動跟蹤邏輯到單獨對象(網格適配器或特定網格片段)中可能會更好):

public class MyActivity extends Activity implements ScrollAwareGridView.ImmediateScrollListener, AdapterView.OnItemClickListener { 

    private static final String TAG = "MyActivity"; 

    /** To start/pause music */ 
    private ImageView mSelectedImage = null; 
    /** position of selected item in the adapter */ 
    private int mSelectedPosition; 
    /** Main grid view */ 
    private ScrollAwareGridView mGrid; 
    /** Adapter for grid view */ 
    private ImageAdapter mAdapter; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Show the layout with the test view 
     setContentView(R.layout.main); 

     mSelectedImage = (ImageView) findViewById(R.id.selectedImage); 

     mGrid = (ScrollAwareGridView) findViewById(R.id.grid); 

     if (null != mGrid) { 
      mAdapter = new ImageAdapter(this); 

      mGrid.setAdapter(mAdapter); 

      mGrid.setImmediateScrollListener(this); 
      mGrid.setOnItemClickListener(this); 
     } 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 

     mSelectedImage.setImageBitmap(null); 
     mSelectedImage.setVisibility(View.GONE); 
     mSelectedPosition = -1; 
    } 

    @Override 
    public void onImmediateScrollChanged() { 
     if (mSelectedPosition >= 0) { 
      int firstPosition = mGrid.getFirstVisiblePosition(); // This is the same as child #0 
      int wantedChild = mSelectedPosition - firstPosition; 

      // Say, first visible position is 8, you want position 10, wantedChild will now be 2 
      // So that means your view is child #2 in the ViewGroup: 
      if (wantedChild < 0 || wantedChild >= mGrid.getChildCount()) { 
       Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen."); 
       mSelectedImage.setVisibility(View.INVISIBLE); 
       return; 
      } else { 
       mSelectedImage.setVisibility(View.VISIBLE); 
      } 

      // Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead. 
      final View selectedView = mGrid.getChildAt(wantedChild); 

      if (null != selectedView && mSelectedImage.getVisibility() == View.VISIBLE) { 
       // Put selected view on new position 
       final ViewGroup.MarginLayoutParams zoomedImageLayoutParams = (ViewGroup.MarginLayoutParams) mSelectedImage.getLayoutParams(); 

       // 200 is difference between zoomed and not zoomed images dimensions 
       // TODO: Avoid hardcoded values and use resources 
       final Integer thumbnailX = mGrid.getLeft() + selectedView.getLeft() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION)/2; 
       final Integer thumbnailY = mGrid.getTop() + selectedView.getTop() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION)/2; 

       zoomedImageLayoutParams.setMargins(thumbnailX, 
         thumbnailY, 
         0, 
         0); 

       mSelectedImage.setLayoutParams(zoomedImageLayoutParams); 
      } 
     } 
    } 

    @Override 
    public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) { 
     mSelectedPosition = position; 

     final Bitmap bm = mAdapter.getImage(position); 

     // Obtain image from adapter, with check if image presented 
     if (bm != null) { 
      final ViewGroup.MarginLayoutParams zoomedImageLayoutParams = (ViewGroup.MarginLayoutParams) mSelectedImage.getLayoutParams(); 

      // 200 is difference between zoomed and not zoomed images dimensions 
      // TODO: Avoid hardcoded values and use resources 
      final Integer thumbnailX = mGrid.getLeft() + view.getLeft() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION)/2; 
      final Integer thumbnailY = mGrid.getTop() + view.getTop() - (ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION - ImageAdapter.GRID_ITEM_DIMENSION)/2; 

      zoomedImageLayoutParams.setMargins(thumbnailX, 
        thumbnailY, 
        0, 
        0); 
      zoomedImageLayoutParams.height = ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION; 
      zoomedImageLayoutParams.width = ImageAdapter.HIGHLIGHTED_GRID_ITEM_DIMENSION; 

      mSelectedImage.setImageBitmap(bm); 
      mSelectedImage.setScaleType(ImageView.ScaleType.CENTER); 
      mSelectedImage.setLayoutParams(zoomedImageLayoutParams); 
      mSelectedImage.setVisibility(View.VISIBLE); 
     } 
    } 
} 

以下是GridView的適配器。但是沒有什麼具體在這其中涉及到滾動跟蹤(大多數的代碼中,我從this answer重複使用):

public class ImageAdapter extends BaseAdapter { 

    private static final String TAG = "ImageAdapter"; 
    /** For creation of child ImageViews */ 
    private Context mContext; 

    public static final Integer[] IMAGES_RESOURCES = { 
     R.drawable.image001, R.drawable.image002, R.drawable.image003, R.drawable.image004, 
     R.drawable.image005, R.drawable.image006, R.drawable.image007, R.drawable.image008, 
     R.drawable.image009, R.drawable.image010, R.drawable.image011, R.drawable.image012, 
     R.drawable.image013, R.drawable.image014, R.drawable.image015, R.drawable.image016, 
     R.drawable.image017, R.drawable.image018, R.drawable.image019, R.drawable.image020, 
     R.drawable.image021, R.drawable.image022, R.drawable.image023, R.drawable.image024, 
     R.drawable.image025, R.drawable.image026, R.drawable.image027, R.drawable.image028, 
     R.drawable.image029, R.drawable.image030, R.drawable.image031, R.drawable.image032, 
     R.drawable.image033, R.drawable.image034, R.drawable.image035, R.drawable.image036, 
     R.drawable.image037, R.drawable.image038, R.drawable.image039, R.drawable.image040, 
     R.drawable.image041, R.drawable.image042, R.drawable.image043, R.drawable.image044, 
     R.drawable.image045, R.drawable.image046, R.drawable.image047, R.drawable.image048, 
     R.drawable.image049, R.drawable.image050 
    }; 

    // TODO: use resources for that sizes, otherwise You'll GET PROBLEMS on other displays! 
    public final static int GRID_ITEM_DIMENSION = 300; 
    public final static int HIGHLIGHTED_GRID_ITEM_DIMENSION = 500; 

    private Bitmap mHolder = null; 
    private static final int CACHE_SIZE = 50 * 1024 * 1024; // 8 MiB cache 
    /** Cache to store all decoded images */ 
    private LruCache<Integer, Bitmap> mBitmapsCache = new LruCache<Integer, Bitmap>(CACHE_SIZE) { 

     @Override 
     protected int sizeOf(final Integer key, final Bitmap value) { 
      return value.getByteCount(); 
     } 

     @Override 
     protected void entryRemoved(final boolean evicted, final Integer key, final Bitmap oldValue, final Bitmap newValue) { 
      if (!oldValue.equals(mHolder)) { 
       oldValue.recycle(); 
      } 
     } 
    }; 

    // Constructor 
    public ImageAdapter(Context c){ 
     mContext = c; 
     mHolder = BitmapFactory.decodeResource(c.getResources(), R.drawable.ic_launcher, null); 
    } 

    @Override 
    public int getCount() { 
     return IMAGES_RESOURCES.length; 
    } 

    @Override 
    public Object getItem(int position) { 
     return IMAGES_RESOURCES[position]; 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ImageView imageView; 

     if (convertView == null) { 
      imageView = new ImageView(mContext); 

      imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 
      imageView.setLayoutParams(new GridView.LayoutParams(GRID_ITEM_DIMENSION, GRID_ITEM_DIMENSION)); 
     } else { 
      imageView = (ImageView) convertView; 
     } 

     final Bitmap itemBitmap = mBitmapsCache.get(IMAGES_RESOURCES[position]); 

     if (itemBitmap == null || itemBitmap.isRecycled()) { 
      Log.e(TAG, position + " is missed, launch decode for " + IMAGES_RESOURCES[position]); 
      imageView.setImageBitmap(mHolder); 
      mBitmapsCache.put(IMAGES_RESOURCES[position], mHolder); 
      new BitmapWorkerTask(mBitmapsCache, mContext.getResources(), this).execute(IMAGES_RESOURCES[position]); 
     } else { 
      Log.e(TAG, position + " is here for " + IMAGES_RESOURCES[position]); 
      imageView.setImageBitmap(itemBitmap); 
     } 

     return imageView; 
    } 

    /** 
    * Obtains image at position (if there's only holder, then null to be returned) 
    * 
    * @param position int position in the adapter 
    * 
    * @return {@link Bitmap} image at position or null if image is not loaded yet 
    */ 
    public Bitmap getImage(final int position) { 

     final Bitmap bm = mBitmapsCache.get(IMAGES_RESOURCES[position]); 

     return ((mHolder.equals(bm) || bm == null) ? null : bm.copy(Bitmap.Config.ARGB_8888, false)); 
    } 

    /** AsyncTask for decoding images from resources */ 
    static class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { 
     private int data = 0; 
     private final LruCache<Integer, Bitmap> mCache; 
     private final Resources mRes; 
     private final BaseAdapter mAdapter; 

     public BitmapWorkerTask(LruCache<Integer, Bitmap> cache, Resources res, BaseAdapter adapter) { 
      // nothing to do here 
      mCache = cache; 
      mRes = res; 
      mAdapter = adapter; 
     } 

     // Decode image in background. 
     @Override 
     protected Bitmap doInBackground(Integer... params) { 
      data = params[0]; 
      // Use sizes for selected bitmaps for good up-scaling 
      return decodeSampledBitmapFromResource(mRes, data, GRID_ITEM_DIMENSION, GRID_ITEM_DIMENSION); 
     } 

     // Once complete, see if ImageView is still around and set bitmap. 
     @Override 
     protected void onPostExecute(Bitmap bitmap) { 
      mCache.put(data, bitmap); 
      mAdapter.notifyDataSetChanged(); 
     } 
    } 

    public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
                 int reqWidth, int reqHeight) { 

     // First decode with inJustDecodeBounds=true to check dimensions 
     final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeResource(res, resId, options); 

     // Calculate inSampleSize 
     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     // Decode bitmap with inSampleSize set 
     options.inJustDecodeBounds = false; 
     options.outHeight = GRID_ITEM_DIMENSION; 
     options.outWidth = GRID_ITEM_DIMENSION; 
     return BitmapFactory.decodeResource(res, resId, options); 
    } 

    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { 
     // Raw height and width of image 
     final int height = options.outHeight; 
     final int width = options.outWidth; 
     int inSampleSize = 1; 

     if (height > reqHeight || width > reqWidth) { 

      // Calculate ratios of height and width to requested height and width 
      final int heightRatio = Math.round((float) height/(float) reqHeight); 
      final int widthRatio = Math.round((float) width/(float) reqWidth); 

      // Choose the smallest ratio as inSampleSize value, this will guarantee 
      // a final image with both dimensions larger than or equal to the 
      // requested height and width. 
      inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; 
     } 

     return inSampleSize; 
    } 
} 
+0

謝謝sandrstar的幫助。 –

+0

它適合你嗎? – sandrstar