0

我正在尝试创建图像的水平滑动网格。我正在使用带有适配器的 Gallery 视图,该适配器为我提供包含要显示的图像视图的 TableLayouts。一切看起来都很好,但是当我触摸屏幕 (MotionEvent.ACTION_DOWN) 时,Gallery 会突然向左或向右移动,从而难以滑动(当前显示的孩子被带到前面)。关于如何解决它的任何线索?这是最好的方法吗?

编辑:这里是源代码

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 或者如果您确切地知道子结构一旦检测到就分派点击,那就没问题了。

4

1 回答 1

0

画廊有一个中心锁定机制,这将使它在打字时很难。你可以试试这个链接

我已经看到了这一点,并且很适合你正在做的事情。

于 2011-08-19T10:32:27.957 回答