0

我正在研究一个带中心锁的 Horizo​​ntalScrollview。它基于此 stackoverflow 线程中的一些代码:

Horizo​​ntalScrollView 与 imageviews 作为一个孩子,而在屏幕中滚动图像的中心应该播放动画?

问题是它没有正确支持方向键导航。它不会滚动到下一个项目,而是跳转位置。我修改了代码,使其正确地与 D-Pad 导航一起使用,但这使得 Touch 滚动不起作用。同样出于某种原因,即使正确添加了 TextView,点击侦听器似乎也被删除了。无论如何,现在的主要问题是,如果我重新添加 onScrollChange 事件的代码,它对 Touch 正常工作,但是如果项目不在屏幕上,则 D-Pad 导航可以跳过一个项目,然后再回到屏幕上。

以下是正在使用的 xml.layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/serenity_bonsai_logo"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <LinearLayout
       android:id="@+id/main_menu_row1"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
       android:orientation="horizontal" >

       <DigitalClock
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:background="#50000000"
           android:textColor="#F0F0F0"
           android:textSize="20sp" />
    </LinearLayout>

    <us.nineworlds.serenity.widgets.CenterLockHorizontalScrollview
        android:id="@+id/mainGalleryMenu"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#50000000"
        android:layout_centerInParent="true"
        android:clickable="true"
        android:scrollbars="none" >

        <LinearLayout
           android:layout_width="fill_parent"
           android:layout_height="150dp"
           android:layout_gravity="center_vertical"
           android:background="@android:color/transparent"
           android:orientation="horizontal"
           android:clickable="true" >
        </LinearLayout>
     </us.nineworlds.serenity.widgets.CenterLockHorizontalScrollview>

</RelativeLayout>

我知道问题在于 onScrollChange 方法以及它如何计算应该是新的中心视图,但不确定如何让 D-Pad 和触摸滚动很好地一起播放。这是CenterLockHorizo​​ntalScrollView 类的相关代码。

public class CenterLockHorizontalScrollview extends HorizontalScrollView {
private ListAdapter mAdapter;

private int mCenterViewPosition = -1;
private MenuDataSetObserver menuDataObserver;
private OnItemSelectedListener selectedItemListener;
private boolean keypadScrollEvent = false;

public CenterLockHorizontalScrollview(Context context, AttributeSet attrs) {
    super(context, attrs);

    this.setHorizontalFadingEdgeEnabled(true);
    this.setHorizontalScrollBarEnabled(false);
    this.setFadingEdgeLength(5);
    this.setSmoothScrollingEnabled(true);
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {

    super.onLayout(changed, l, t, r, b);

    if (getChildCount() == 0) {
        return;
    }

    initCenterView();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    if (getChildCount() == 0)
        return;

    ViewGroup parent = (ViewGroup) getChildAt(0);

    if (parent.getChildCount() == 0)
        return;

    View FirstChild = parent.getChildAt(0);

    int LeftPadding = (getWidth() / 2)
            - (FirstChild.getMeasuredWidth() / 2);

    View LastChild = parent.getChildAt(getChildCount() - 1);

    int RightPadding = (getWidth() / 2)
            - (LastChild.getMeasuredWidth() / 2);

    if (parent.getPaddingLeft() != LeftPadding
            && parent.getPaddingRight() != RightPadding) {
        parent.setPadding(LeftPadding, parent.getPaddingTop(),
                RightPadding, parent.getPaddingBottom());
        requestLayout();
    }
}

/* (non-Javadoc)
 * @see android.view.View#onKeyDown(int, android.view.KeyEvent)
 */
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    int totalItems = 0;
    if (mAdapter.getCount() > 0) {
        totalItems = mAdapter.getCount();
    }

    int currentPosition = mCenterViewPosition;

    if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
        if (currentPosition > 0) {
            setSelectedIndex(currentPosition - 1);
        } else {
            setSelectedIndex(totalItems - 1);
        }
        keypadScrollEvent = true;
        scrollToSelectedIndex();
        keypadScrollEvent = false;
        return true;
    }

    if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
        if (currentPosition < totalItems - 1) {
            setSelectedIndex(currentPosition + 1);
        } else {
            setSelectedIndex(0);
        }
        keypadScrollEvent = true;
        scrollToSelectedIndex();
        keypadScrollEvent = false;
        return true;
    }

    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER ||
        keyCode == KeyEvent.KEYCODE_ENTER) {
        ViewGroup parent = (ViewGroup) getChildAt(0);
        View view = parent.getChildAt(mCenterViewPosition);
        view.setOnClickListener(new GalleryOnClickListener(view.getContext()));
        view.performClick();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}


private int getCenterPositionFromView() {

    int scrollingCenterView = getScrollingCenterView();
    if (mCenterViewPosition != scrollingCenterView) {
        ViewGroup parent = (ViewGroup) getChildAt(0);
        View view = parent.getChildAt(scrollingCenterView);
        selectedItemListener.onItemSelected(view, scrollingCenterView, scrollingCenterView);
        mCenterViewPosition = scrollingCenterView;
    }

    return scrollingCenterView;
}


private int getScrollingCenterView() {
     if(getChildCount() == 0)
            return -1;

        int centerView= 0;
        int centerX = getScrollX() + (getWidth() / 2); 

        ViewGroup parent = (ViewGroup) getChildAt(0);

        if(parent.getChildCount() == 0)
            return -1;

        View child = parent.getChildAt(0);

        while(child != null && child.getRight() <= centerX && centerView < parent.getChildCount())
        {
            centerView++;
            child = parent.getChildAt(centerView);
        }

        if(centerView >= parent.getChildCount()) {
            centerView = parent.getChildCount() - 1;
        }

        return centerView;      

}


public int getCenterViewPosition() {
    return mCenterViewPosition;
}

public ListAdapter getAdapter() {
    return mAdapter;
}

public void setAdapter(ListAdapter mAdapter) {

    this.mAdapter = mAdapter;
    if (menuDataObserver != null) {
        mAdapter.unregisterDataSetObserver(menuDataObserver);
    }
    mAdapter.registerDataSetObserver(new MenuDataSetObserver());
}

private void fillViewWithAdapter() {
    if (getChildCount() == 0 || mAdapter == null)
        return;

    ViewGroup parent = (ViewGroup) getChildAt(0);

    parent.removeAllViews();

    for (int i = 0; i < mAdapter.getCount(); i++) {
        parent.addView(mAdapter.getView(i, null, parent));
    }
    setSelectedIndex(0);
}



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

    if (keypadScrollEvent == false) {
        getCenterPositionFromView();
    }
    initCenterView();
}

private void initCenterView() {
    Log.i(getClass().getName(), "initCenterView");

    if (getChildCount() == 0)
        return;

    ViewGroup parent = (ViewGroup) getChildAt(0);

    if (parent.getChildCount() == 0)
        return;

    int centerView = getCenterViewPosition();

    if (centerView == -1) {
        mCenterViewPosition = 0;
        centerView = 0;
    }

    if (centerView != -1 && centerView != mCenterViewPosition
            && parent.getChildAt(0).getLeft() >= 0) {
        scrollToSelectedIndex();
    }

    if (centerView < 0 || centerView > parent.getChildCount())
        return;

    for (int i = 0; i <= parent.getChildCount(); i++) {

        if (! (parent.getChildAt(i) instanceof TextView)) {
            continue;
        }

        if (i == centerView) {
            // Start Animation
            //setSelectedIndex(i);
            //scrollToSelectedIndex();
            return;
        } else {
            // Remove Animation for other Views
        }
    }

}

public int getSelectedIndex() {
    return getCenterViewPosition();
}

public void setSelectedIndex(int index) {
    Log.i(getClass().getName(), "setSelectedIndex");

    if (getChildCount() == 0)
        return;

    ViewGroup parent = (ViewGroup) getChildAt(0);

    if (index < 0 || index > parent.getChildCount()) {
        throw new ArrayIndexOutOfBoundsException(index);
    }

    mCenterViewPosition = index;

    //onSelectedItemChanged.onSelectedChanged(this, mCenterViewPosition);
    selectedItemListener.onItemSelected(parent.getChildAt(index), index, 0); 

    requestLayout();
}

protected void scrollToSelectedIndex() {

    ViewGroup parent = (ViewGroup) getChildAt(0);

    View child = parent.getChildAt(mCenterViewPosition);

    if (child == null) {
        return;
    }

    int offsetX = ((child.getLeft() + child.getRight()) / 2) - (this.getWidth() / 2);

    smoothScrollTo(offsetX, 0);
}

public class MenuDataSetObserver extends DataSetObserver {

    @Override
    public void onChanged() {
        fillViewWithAdapter();
    }

}

public OnItemSelectedListener getOnItemSelectedListener() {
    return selectedItemListener;
}

public void setOnItemSelectedListener(OnItemSelectedListener selectedItemListener) {
    this.selectedItemListener = selectedItemListener;
}
}

如果不检查 onScrollChange 中的中心,D-Pad 导航可以正常工作,但触摸滚动不能。

4

1 回答 1

0

我的建议是不要覆盖 onKeyDown 事件,而是附加一个 onClickListener。您是否考虑过使用 ViewPager 代替您覆盖 ViewPager 宽度以考虑其中包含的项目?

于 2013-04-22T17:27:42.183 回答