2

I'm using scrollable static cards as an item selector (scroll through until you find one, then use the onItemSelected event to catch the click). It works, but it doesn't show the scroll bar on the bottom like it does for menu items and all standard system cards. Is there a way to enable it?

Here's the adapter code:

private class FooCardScrollAdapter extends CardScrollAdapter {
    @Override
    public int findIdPosition(Object id) {
        return -1;
    }

    @Override
    public int findItemPosition(Object item) {
        return mCards.indexOf(item);
    }

    @Override
    public int getCount() {
        return mCards.size();
    }

    @Override
    public Object getItem(int position) {
        return mCards.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        return mCards.get(position).toView();
    }
}
kolosy
  • 3,029
  • 3
  • 29
  • 48

3 Answers3

5

As of XE16 this is now possible by just setting

mCardScrollView.setHorizontalScrollBarEnabled(true);
Ben
  • 1,767
  • 16
  • 32
0

This is a known issue; there is no way to currently get the scroll indicator on a GDK CardScrollView. Please follow issue 256 on our issue tracker to be updated as the GDK evolves!

Tony Allevato
  • 6,429
  • 1
  • 29
  • 34
0

So I had the same problem as you. To solve it, I had to create my own scrollbar view. It's not as good as the built-in one for the Mirror API because it doesn't handle fling scrolling, but It's the best we can do until google releases their own.

First we create a custom view SimulatedScrollBar:

public class SimulatedScrollBar extends View {

private static final String TAG = SimulatedScrollBar.class.getSimpleName();
private static final boolean DEBUG = false;
private static final int WHITE_SCROLLBAR_COLOR = 0xfffefefe;

private int mScrollPosition;
private int mNumItems;
private Paint mPaint;
private float mInnerWidth;
private float mInnerHeight;
private int mOffsetX;
private int mWidth;
private int mHeight;

public SimulatedScrollBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.SimulatedScrollBar,
            0, 0);

    try {
        mScrollPosition = a.getInteger(R.styleable.SimulatedScrollBar_scrollPosition, 0);
        mNumItems = a.getInteger(R.styleable.SimulatedScrollBar_numItems, 0);
    } finally {
        a.recycle();
    }
    init();
}

private void init() {
    mPaint = new Paint();
    mPaint.setColor(WHITE_SCROLLBAR_COLOR);
    mPaint.setStyle(Paint.Style.FILL);
}

public int getScrollPosition() {
    return mScrollPosition;
}

public void setScrollPosition(int scrollPosition) {
    mScrollPosition = scrollPosition;
    invalidate();
    requestLayout();
}

public int getNumItems() {
    return mNumItems;
}

public void setNumItems(int numItems) {
    mNumItems = numItems;
    invalidate();
    requestLayout();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    float xpad = (float)(getPaddingLeft() + getPaddingRight());
    float ypad = (float)(getPaddingTop() + getPaddingBottom());
    mInnerWidth = (float)w - xpad;
    mInnerHeight = (float)h - ypad;
    if (DEBUG) Log.i(TAG, "onSizeChanged() mInnerWidth=" + mInnerWidth + " mInnerHeight=" + mInnerHeight);
}

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    float widthFraction = mNumItems > 0 ? 1.0f / (float)mNumItems : 0;
    float scrollFraction = mNumItems > 0 ? (float)mScrollPosition / (float)mNumItems : 0;
    mOffsetX = (int)(mInnerWidth * scrollFraction);
    mWidth = (int)(mInnerWidth * widthFraction);
    mHeight = (int)mInnerHeight;
    Rect rect = new Rect(mOffsetX, 0, mOffsetX + mWidth, mHeight);
    if (DEBUG) Log.i(TAG, "onDraw() mOffsetX=" + mOffsetX + " mWidth=" + mWidth + " mHeight=" + mHeight
            + " mScrollPosition=" + mScrollPosition + " mNumItems=" + mNumItems);
    canvas.drawRect(rect, mPaint);
}

}

We need an attribute file `attrs.xml' to support configuring the view:

<resources>
    <declare-styleable name="SimulatedScrollBar">
        <attr name="scrollPosition" format="integer"/>
        <attr name="numItems" format="integer"/>
    </declare-styleable>
</resources>

Now we make a layout card_scroll_layout.xml which has the card scroll view and our scroll bar overlaying:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.chanapps.glass.chan"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black">

<com.google.android.glass.widget.CardScrollView
        android:id="@+id/card_scroll_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

<ProgressBar
        android:id="@+id/progress_bar"
        style="?android:attr/progressBarStyleHorizontal"
        android:indeterminate="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        />

<com.chanapps.glass.chan.view.SimulatedScrollBar
        android:id="@+id/simulated_scroll_bar"
        android:layout_width="match_parent"
        android:layout_height="10px"
        android:layout_gravity="bottom"
        custom:numItems="0"
        custom:scrollPosition="0"
        />

</FrameLayout>

Here's what you put in your onCreate() to hook the pieces together:

mSimulatedScrollBar = (SimulatedScrollBar)rootLayout.findViewById(R.id.simulated_scroll_bar);
mSimulatedScrollBar.setScrollPosition(0);
mSimulatedScrollBar.setNumItems(mAdapter.getCount());

mCardScrollView = (CardScrollView)rootLayout.findViewById(R.id.card_scroll_view);
mCardScrollView.setAdapter(mAdapter);
mCardScrollView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if (mSimulatedScrollBar != null)
            mSimulatedScrollBar.setScrollPosition(position);
    }
    @Override
    public void onNothingSelected(AdapterView<?> parent) {
    }
});
mCardScrollView.activate();

Now when you slide through the list, you'll see the scroll bar at the bottom tracking the list position. If your adapter changes sizes, update the number of items and scroll position in the adapter or in an onLoadFinished() loader callback.

johnarleyburns
  • 1,532
  • 12
  • 13