处理D-Pad的ScrollChange和自定义Horizo​​ntalScrollView的触摸

时间:2013-04-20 15:35:28

标签: android google-tv

我正在使用Center锁定的Horizo​​ntalScrollview。它基于此stackoverflow线程中的一些代码:

HorizontalScrollView with imageviews as a child and while scrolling the center of the image in the screen should play animation?

问题是它不能正确支持D-Pad导航。它不会滚动到下一个项目,而是跳转位置。我修改了代码,以便正确使用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导航中没有中心检查,但是触摸滚动没有。

1 个答案:

答案 0 :(得分:0)

我的建议是不要覆盖onKeyDown事件,而是附加一个onClickListener。您是否考虑使用ViewPager,而是覆盖ViewPager宽度以考虑?

中包含的项目