2011-08-19 145 views
0

我試圖創建圖像的水平滑動網格。我正在使用帶有適配器的Gallery視圖,該適配器向我提供包含要顯示的圖像視圖的TableLayouts。一切看起來都很好,但是當我觸摸屏幕(MotionEvent.ACTION_DOWN)時,畫廊突然向左或向右移動,難以滑動(當前顯示的小孩被帶到最前面)。有關如何解決它的任何線索?這是最好的方法嗎?畫廊內的大視圖問題

編輯:這裏的源代碼

import java.util.LinkedList; 
import java.util.WeakHashMap; 
import android.content.Context; 
import android.graphics.Color; 
import android.util.AttributeSet; 
import android.view.GestureDetector; 
import android.view.Gravity; 
import android.view.KeyEvent; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.Adapter; 
import android.widget.AdapterView; 
import android.widget.BaseAdapter; 
import android.widget.Gallery; 
import android.widget.GridView; 
import android.widget.ImageView; 
import android.widget.SpinnerAdapter; 
import android.widget.TableLayout; 
import android.widget.TableRow; 
public class Dock extends Gallery { 
private Adapter mAdapter; 
private int numLines=1; 
private int numColumns=1; 
protected int columnWidth = GridView.AUTO_FIT; 
private OnItemClickListener myOnItemClickListener; 
private OnItemLongClickListener myOnItemLongClickListener; 
private OnItemSelectedListener myOnItemSelectedClickListener; 
private GestureDetector interceptGest = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener(){ 
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
     return true; 
    }; 
}); 
public int columnSpacing = 10; 
private CustomAdapter adapt; 
public Dock(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    initDock(); 
} 
public Dock(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    initDock(); 
} 
public Dock(Context context) { 
    super(context); 
    initDock(); 
} 
private void initDock(){ 
    this.setSpacing(50); 
    this.setHorizontalFadingEdgeEnabled(false); 
    this.setGravity(Gravity.CENTER); 
    this.setBackgroundColor(Color.GREEN); 
    this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
} 
public int getNumLines() { 
    return numLines; 
} 
public void setNumLines(int numLines) { 
    this.numLines = numLines; 
} 
public int getNumColumns() { 
    return numColumns; 
} 
public void setNumColumns(int numColumns) { 
    this.numColumns = numColumns; 
} 
public void setOnItemClickListener(
     android.widget.AdapterView.OnItemClickListener listener) { 
    this.myOnItemClickListener = listener; 
} 

public void setOnItemLongClickListener(
     android.widget.AdapterView.OnItemLongClickListener listener) { 
    this.myOnItemLongClickListener = listener; 
} 
public void setOnItemSelectedListener(
     android.widget.AdapterView.OnItemSelectedListener listener) { 
    this.myOnItemSelectedClickListener = listener; 
} 
public void setAdapter(final SpinnerAdapter adapter) { 
    adapt = new CustomAdapter(adapter); 
    mAdapter = adapter; 
    super.setAdapter(adapt); 
} 

@Override 
public SpinnerAdapter getAdapter() { 
    return (SpinnerAdapter) mAdapter; 
} 
private class CustomGrid extends TableLayout{ 
    private AdapterView<Adapter> mAdapterView = new AdapterView<Adapter>(getContext()){ 
     @Override 
     public Adapter getAdapter() { 
      return mAdapter; 
     } 
     @Override 
     public View getSelectedView() { 
      return Dock.this.findFocus(); 
     } 
     @Override 
     public void setAdapter(Adapter adapter) { 
      Dock.this.setAdapter((SpinnerAdapter) adapter); 
     } 
     @Override 
     public void setSelection(int position) { 
      Dock.this.setSelection(position); 
     } 
    }; 
    private int page; 
    private Adapter adapter; 
    protected android.widget.AdapterView.OnItemClickListener mOnItemClickListener; 
    protected android.widget.AdapterView.OnItemLongClickListener mOnItemLongClickListener; 
    protected android.widget.AdapterView.OnItemSelectedListener mOnItemSelectedListener; 
    public CustomGrid(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initGrid(); 
    } 
    public CustomGrid(Context context) { 
     super(context); 
     initGrid(); 
    } 
    private void initGrid(){ 
     this.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT)); 
     this.setFocusable(false); 
    } 
    public void setPage(int position) { 
     this.page = position; 
    } 
    public void setAdapter(BaseAdapter adapter) { 
     this.adapter = adapter; 
    } 
    public void setOnItemClickListener(
      android.widget.AdapterView.OnItemClickListener onItemClickListener) { 
     this.mOnItemClickListener = onItemClickListener; 
    } 
    public void setOnItemLongClickListener(
      android.widget.AdapterView.OnItemLongClickListener onItemLongClickListener) { 
     this.mOnItemLongClickListener = onItemLongClickListener; 
    } 
    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     boolean ret = false; 
     if(ev.getAction()==MotionEvent.ACTION_MOVE) 
      ret = true; 
     else 
      ret = super.onInterceptTouchEvent(ev); 
     return ret; 
    } 
    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     if(ev.getAction()==MotionEvent.ACTION_MOVE) 
      return false; 
     else 
      return super.onTouchEvent(ev); 
    } 
    public void setOnItemSelectedListener(
      android.widget.AdapterView.OnItemSelectedListener onItemSelectedListener) { 
     this.mOnItemSelectedListener = onItemSelectedListener; 
    } 
    private View getCachedView(int position, ViewGroup parent) { 
     int p = position + page*getNumColumns()*getNumLines(); 
     if(p<adapter.getCount()) 
      return adapter.getView(p, null, parent); 
     else 
      return null; 
    } 
    private void refreshGrid(){ 
     if(mAdapter==null) 
      return; 
     int count=0; 
     if(numLines>1) 
      this.setPadding(5, 0, 5, 0); 
     TableRow line = null; 
     View view = null; 
     for(int i = 0; i<numLines; i++){ 
      line = new TableRow(getContext()); 
      line.setBaselineAligned(false); 
      line.setGravity(Gravity.CENTER); 
      line.setFocusable(false); 
      for(int j = 0; j< numColumns; j++){ 
       this.setColumnShrinkable(j, true); 
       this.setColumnStretchable(j, true); 
       view = getCachedView(count, line); 
       if(view!=null){ 
        final int position = count + page*getNumColumns()*getNumLines(); 
        view.setOnClickListener(new OnClickListener() { 
         @Override 
         public void onClick(View arg0) { 
          if(mOnItemClickListener!=null) 
           mOnItemClickListener.onItemClick(mAdapterView, arg0, position, mAdapter.getItemId(position)); 
         } 
        }); 
        view.setOnLongClickListener(new OnLongClickListener() { 
         @Override 
         public boolean onLongClick(View arg0) { 
          if(mOnItemLongClickListener!=null) 
           return mOnItemLongClickListener.onItemLongClick(mAdapterView, arg0, position, mAdapter.getItemId(position)); 
          else return false; 
         } 
        }); 
        view.setOnFocusChangeListener(new OnFocusChangeListener() { 
         @Override 
         public void onFocusChange(View arg0, boolean arg1) { 
          if(mOnItemSelectedListener!=null&&arg1){ 
           mOnItemSelectedListener.onItemSelected(mAdapterView, arg0, position, mAdapter.getItemId(position)); 
          } 
         } 
        }); 
        view.setFocusable(false); 
        line.addView(view); 
       } 
       count++; 
      } 
      if(numLines>1) 
       while(line.getChildCount()<numColumns){ 
        View v = this.getEmptyView(); 
        v.setFocusable(false); 
        line.addView(v); 
       } 
      this.addView(line); 
     } 
    } 
    private View getEmptyView() { 
     ImageView ret = new ImageView(getContext()); 
     ret.setBackgroundColor(Color.TRANSPARENT); 
     return ret; 
    } 
} 
private class CustomAdapter extends BaseAdapter{ 
    private WeakHashMap<Integer,CustomGrid> cache = new WeakHashMap<Integer,CustomGrid>(); 
    private LinkedList<Integer> cacheId = new LinkedList<Integer>(); 
    private Adapter adapter; 
    public CustomAdapter(Adapter a){ 
     super(); 
     adapter = a; 
    } 
    public long getItemId(int position) { 
     return position; 
    } 
    public Object getItem(int position) { 
     return null; 
    } 
    public int getCount() { 
     int n = adapter.getCount()/(numColumns*numLines); 
     if(adapter.getCount()%(numColumns*numLines)!=0) 
      n++; 
     return n; 
    } 
    private CustomGrid getPage(final int position){ 
     CustomGrid ret = new CustomGrid(getContext()); 
     ret.setPage(position); 
     ret.setAdapter((BaseAdapter) adapter); 
     ret.setOnItemClickListener(new OnItemClickListener() { 
      public void onItemClick(AdapterView<?> adapterV, View v, 
        int pos, long id) { 
       //int page = position; 
       if(myOnItemClickListener!=null){ 
        myOnItemClickListener.onItemClick(adapterV, v, pos, adapter.getItemId(pos)); 
       } 
      } 
     }); 
     ret.setOnItemLongClickListener(new OnItemLongClickListener() { 
      public boolean onItemLongClick(AdapterView<?> adapterV, 
        View arg1, int pos, long arg3) { 
       //int page = position; 
       if(myOnItemLongClickListener!=null){ 
        return myOnItemLongClickListener.onItemLongClick(adapterV, arg1, pos, adapter.getItemId(pos)); 
       } 
       else 
        return false; 
      } 
     }); 
     ret.setOnItemSelectedListener(new OnItemSelectedListener() { 
      public void onItemSelected(AdapterView<?> adapterV, 
        View arg1, int pos, long arg3) { 
       if(myOnItemSelectedClickListener!=null){ 
        myOnItemSelectedClickListener.onItemSelected(adapterV, arg1, pos, adapter.getItemId(pos)); 
       } 
      } 
      public void onNothingSelected(AdapterView<?> arg0) { 
       if(myOnItemSelectedClickListener!=null) 
        myOnItemSelectedClickListener.onNothingSelected(arg0); 
      } 
     }); 
     ret.setLayoutParams(new Gallery.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
     ret.setGravity(Gravity.CENTER); 
     ret.setBackgroundColor(Color.BLUE); 
     ret.refreshGrid(); 
     return ret; 
    } 
    public View getView(int position, View convertView, ViewGroup parent) { 
     convertView = cache.get(position); 
     if(convertView==null){ 
      convertView = getPage(position); 
      while(cache.size()>3){ 
       cache.remove(cacheId.removeFirst()); 
      } 
      cache.put(position, (CustomGrid) convertView); 
      cacheId.add(position); 
      if(position<getCount()){ 
       cache.put(position+1, getPage(position+1)); 
       cacheId.add(position+1); 
      } 
     } 
     return convertView; 
    } 
    public void flush() { 
     cache.clear(); 
     cacheId.clear(); 
    } 
}; 
public void setColumnWidth(int width) { 
    this.columnWidth = width; 
} 
public void setColumnMargin(int margin){ 
    this.columnSpacing = margin; 
} 
private MotionEvent primTouch; 
@Override 
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
     float velocityY) { 
    if(e1!=null&&e2!=null){ 
     float dist = e1.getX()-e2.getX(); 
     if(Math.abs(dist)>30){ 
      if(dist>0) 
       return onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_RIGHT)); 
      else 
       return onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_LEFT)); 
     } 
    } 
    return true; 
} 
private MotionEvent interm; 
private boolean scrollingHorizontally=false; 


public void flush(){ 
    adapt.flush(); 
} 
@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    if(ev.getAction()==MotionEvent.ACTION_DOWN) 
     primTouch = ev; 
    if(ev.getAction()==MotionEvent.ACTION_MOVE) 
     return true; 
    else 
     return scrollingHorizontally; 
} 
@Override 
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 
    scrollingHorizontally = true; 
    return super.onScroll(e1, e2, distanceX, distanceY); 
} 
@Override 
public boolean onTouchEvent(MotionEvent event) { 
    switch(event.getAction()) { 
    case MotionEvent.ACTION_DOWN: 
     primTouch=event; 
     return super.onTouchEvent(event); 
    case MotionEvent.ACTION_MOVE: 
     scrollingHorizontally=true; 
     break; 
    case MotionEvent.ACTION_UP: 
    case MotionEvent.ACTION_CANCEL: 
     scrollingHorizontally = false; 
     if(primTouch!=null){ 
      float dist = primTouch.getX()-event.getX(); 
      if(Math.abs(dist)>30){ 
       if(dist>0) 
        return onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_RIGHT)); 
       else 
        return onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_LEFT)); 
      } 
     } 
     break; 
    } 
    return super.onTouchEvent(event); 
} 
} 

編輯2:我想通了,如果我處理函數onInterceptTouchEvent(MotionEvent EV)(當我將它設置爲總是返回true),在所有觸摸事件問題消失,但在子項上設置的任何onClickListener被禁用。如果您使用onItemClickListener或者如果您確切知道發現一次檢測到的點擊的子結構,那就沒問題了。

+0

您應該添加您的代碼以供參考。 – user370305

回答

0

畫廊有一箇中心鎖定機制,這將使它困難時sypeing。你可以試試這個LINK

我已經看到這在行動,並會漂亮適合你在做什麼。

+0

它似乎沒有工作。它延伸了視圖並且不響應任何事件。 –

+0

'沒有迴應事件'我想那部分是棘手的。但我確實設法使它工作。 – Samuel

+0

肯定棘手,但它現在xD。我正在使用此視圖的自定義版本。非常感謝:D –