1. 程式人生 > >android 橫向可滑動的圖片

android 橫向可滑動的圖片

忘記在哪個大神哪裡淘來的程式碼,如有侵權請告知,謝謝。

直接將下面程式碼放入專案

/*
 * Copyright (C) 2014 The Android Open Source Project.
 *
 *        [email protected]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.taihua.ckshop.util;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;



public class HorizontalGridView extends BaseGridView {

    private boolean mFadingLowEdge;
    private boolean mFadingHighEdge;

    private Paint mTempPaint = new Paint();
    private Bitmap mTempBitmapLow;
    private LinearGradient mLowFadeShader;
    private int mLowFadeShaderLength;
    private int mLowFadeShaderOffset;
    private Bitmap mTempBitmapHigh;
    private LinearGradient mHighFadeShader;
    private int mHighFadeShaderLength;
    private int mHighFadeShaderOffset;
    private Rect mTempRect = new Rect();

    public HorizontalGridView(Context context) {
        this(context, null);
    }

    public HorizontalGridView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HorizontalGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mLayoutManager.setOrientation(RecyclerView.HORIZONTAL);
        initAttributes(context, attrs);
    }

    protected void initAttributes(Context context, AttributeSet attrs) {
        initBaseGridViewAttributes(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbHorizontalGridView);
        setRowHeight(a);
        setNumRows(a.getInt(R.styleable.lbHorizontalGridView_numberOfRows, 1));
        a.recycle();
        setWillNotDraw(false);
        mTempPaint = new Paint();
        mTempPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    }

    void setRowHeight(TypedArray array) {
        TypedValue typedValue = array.peekValue(R.styleable.lbHorizontalGridView_rowHeight);
        int size;
        if (typedValue != null && typedValue.type == TypedValue.TYPE_DIMENSION) {
            size = array.getDimensionPixelSize(R.styleable.lbHorizontalGridView_rowHeight, 0);
        } else {
            size = array.getInt(R.styleable.lbHorizontalGridView_rowHeight, 0);
        }
        setRowHeight(size);
    }

    /**
     * Set the number of rows.  Defaults to one.
     */
    public void setNumRows(int numRows) {
        mLayoutManager.setNumRows(numRows);
        requestLayout();
    }

    /**
     * Set the row height.
     *
     * @param height May be WRAP_CONTENT, or a size in pixels. If zero,
     * row height will be fixed based on number of rows and view height.
     */
    public void setRowHeight(int height) {
        mLayoutManager.setRowHeight(height);
        requestLayout();
    }

    /**
     * Set fade out left edge to transparent.   Note turn on fading edge is very expensive
     * that you should turn off when HorizontalGridView is scrolling.
     */
    public final void setFadingLeftEdge(boolean fading) {
        if (mFadingLowEdge != fading) {
            mFadingLowEdge = fading;
            if (!mFadingLowEdge) {
                mTempBitmapLow = null;
            }
            invalidate();
        }
    }

    /**
     * Return true if fading left edge.
     */
    public final boolean getFadingLeftEdge() {
        return mFadingLowEdge;
    }

    /**
     * Set left edge fading length in pixels.
     */
    public final void setFadingLeftEdgeLength(int fadeLength) {
        if (mLowFadeShaderLength != fadeLength) {
            mLowFadeShaderLength = fadeLength;
            if (mLowFadeShaderLength != 0) {
                mLowFadeShader = new LinearGradient(0, 0, mLowFadeShaderLength, 0,
                        Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP);
            } else {
                mLowFadeShader = null;
            }
            invalidate();
        }
    }

    /**
     * Get left edge fading length in pixels.
     */
    public final int getFadingLeftEdgeLength() {
        return mLowFadeShaderLength;
    }

    /**
     * Set distance in pixels between fading start position and left padding edge.
     * The fading start position is positive when start position is inside left padding
     * area.  Default value is 0, means that the fading starts from left padding edge.
     */
    public final void setFadingLeftEdgeOffset(int fadeOffset) {
        if (mLowFadeShaderOffset != fadeOffset) {
            mLowFadeShaderOffset = fadeOffset;
            invalidate();
        }
    }

    /**
     * Get distance in pixels between fading start position and left padding edge.
     * The fading start position is positive when start position is inside left padding
     * area.  Default value is 0, means that the fading starts from left padding edge.
     */
    public final int getFadingLeftEdgeOffset() {
        return mLowFadeShaderOffset;
    }

    /**
     * Set fade out right edge to transparent.   Note turn on fading edge is very expensive
     * that you should turn off when HorizontalGridView is scrolling.
     */
    public final void setFadingRightEdge(boolean fading) {
        if (mFadingHighEdge != fading) {
            mFadingHighEdge = fading;
            if (!mFadingHighEdge) {
                mTempBitmapHigh = null;
            }
            invalidate();
        }
    }

    /**
     * Return true if fading right edge.
     */
    public final boolean getFadingRightEdge() {
        return mFadingHighEdge;
    }

    /**
     * Set right edge fading length in pixels.
     */
    public final void setFadingRightEdgeLength(int fadeLength) {
        if (mHighFadeShaderLength != fadeLength) {
            mHighFadeShaderLength = fadeLength;
            if (mHighFadeShaderLength != 0) {
                mHighFadeShader = new LinearGradient(0, 0, mHighFadeShaderLength, 0,
                        Color.BLACK, Color.TRANSPARENT, Shader.TileMode.CLAMP);
            } else {
                mHighFadeShader = null;
            }
            invalidate();
        }
    }

    /**
     * Get right edge fading length in pixels.
     */
    public final int getFadingRightEdgeLength() {
        return mHighFadeShaderLength;
    }

    /**
     * Get distance in pixels between fading start position and right padding edge.
     * The fading start position is positive when start position is inside right padding
     * area.  Default value is 0, means that the fading starts from right padding edge.
     */
    public final void setFadingRightEdgeOffset(int fadeOffset) {
        if (mHighFadeShaderOffset != fadeOffset) {
            mHighFadeShaderOffset = fadeOffset;
            invalidate();
        }
    }

    /**
     * Set distance in pixels between fading start position and right padding edge.
     * The fading start position is positive when start position is inside right padding
     * area.  Default value is 0, means that the fading starts from right padding edge.
     */
    public final int getFadingRightEdgeOffset() {
        return mHighFadeShaderOffset;
    }

    private boolean needsFadingLowEdge() {
        if (!mFadingLowEdge) {
            return false;
        }
        final int c = getChildCount();
        for (int i = 0; i < c; i++) {
            View view = getChildAt(i);
            if (mLayoutManager.getOpticalLeft(view) <
                    getPaddingLeft() - mLowFadeShaderOffset) {
                return true;
            }
        }
        return false;
    }

    private boolean needsFadingHighEdge() {
        if (!mFadingHighEdge) {
            return false;
        }
        final int c = getChildCount();
        for (int i = c - 1; i >= 0; i--) {
            View view = getChildAt(i);
            if (mLayoutManager.getOpticalRight(view) > getWidth()
                    - getPaddingRight() + mHighFadeShaderOffset) {
                return true;
            }
        }
        return false;
    }

    private Bitmap getTempBitmapLow() {
        if (mTempBitmapLow == null
                || mTempBitmapLow.getWidth() != mLowFadeShaderLength
                || mTempBitmapLow.getHeight() != getHeight()) {
            mTempBitmapLow = Bitmap.createBitmap(mLowFadeShaderLength, getHeight(),
                    Bitmap.Config.ARGB_8888);
        }
        return mTempBitmapLow;
    }

    private Bitmap getTempBitmapHigh() {
        if (mTempBitmapHigh == null
                || mTempBitmapHigh.getWidth() != mHighFadeShaderLength
                || mTempBitmapHigh.getHeight() != getHeight()) {
            // TODO: fix logic for sharing mTempBitmapLow
            if (false && mTempBitmapLow != null
                    && mTempBitmapLow.getWidth() == mHighFadeShaderLength
                    && mTempBitmapLow.getHeight() == getHeight()) {
                // share same bitmap for low edge fading and high edge fading.
                mTempBitmapHigh = mTempBitmapLow;
            } else {
                mTempBitmapHigh = Bitmap.createBitmap(mHighFadeShaderLength, getHeight(),
                        Bitmap.Config.ARGB_8888);
            }
        }
        return mTempBitmapHigh;
    }

    @Override
    public void draw(Canvas canvas) {
        final boolean needsFadingLow = needsFadingLowEdge();
        final boolean needsFadingHigh = needsFadingHighEdge();
        if (!needsFadingLow) {
            mTempBitmapLow = null;
        }
        if (!needsFadingHigh) {
            mTempBitmapHigh = null;
        }
        if (!needsFadingLow && !needsFadingHigh) {
            super.draw(canvas);
            return;
        }

        int lowEdge = mFadingLowEdge? getPaddingLeft() - mLowFadeShaderOffset - mLowFadeShaderLength : 0;
        int highEdge = mFadingHighEdge ? getWidth() - getPaddingRight()
                + mHighFadeShaderOffset + mHighFadeShaderLength : getWidth();

        // draw not-fade content
        int save = canvas.save();
        canvas.clipRect(lowEdge + (mFadingLowEdge ? mLowFadeShaderLength : 0), 0,
                highEdge - (mFadingHighEdge ? mHighFadeShaderLength : 0), getHeight());
        super.draw(canvas);
        canvas.restoreToCount(save);

        Canvas tmpCanvas = new Canvas();
        mTempRect.top = 0;
        mTempRect.bottom = getHeight();
        if (needsFadingLow && mLowFadeShaderLength > 0) {
            Bitmap tempBitmap = getTempBitmapLow();
            tempBitmap.eraseColor(Color.TRANSPARENT);
            tmpCanvas.setBitmap(tempBitmap);
            // draw original content
            int tmpSave = tmpCanvas.save();
            tmpCanvas.clipRect(0, 0, mLowFadeShaderLength, getHeight());
            tmpCanvas.translate(-lowEdge, 0);
            super.draw(tmpCanvas);
            tmpCanvas.restoreToCount(tmpSave);
            // draw fading out
            mTempPaint.setShader(mLowFadeShader);
            tmpCanvas.drawRect(0, 0, mLowFadeShaderLength, getHeight(), mTempPaint);
            // copy back to canvas
            mTempRect.left = 0;
            mTempRect.right = mLowFadeShaderLength;
            canvas.translate(lowEdge, 0);
            canvas.drawBitmap(tempBitmap, mTempRect, mTempRect, null);
            canvas.translate(-lowEdge, 0);
        }
        if (needsFadingHigh && mHighFadeShaderLength > 0) {
            Bitmap tempBitmap = getTempBitmapHigh();
            tempBitmap.eraseColor(Color.TRANSPARENT);
            tmpCanvas.setBitmap(tempBitmap);
            // draw original content
            int tmpSave = tmpCanvas.save();
            tmpCanvas.clipRect(0, 0, mHighFadeShaderLength, getHeight());
            tmpCanvas.translate(-(highEdge - mHighFadeShaderLength), 0);
            super.draw(tmpCanvas);
            tmpCanvas.restoreToCount(tmpSave);
            // draw fading out
            mTempPaint.setShader(mHighFadeShader);
            tmpCanvas.drawRect(0, 0, mHighFadeShaderLength, getHeight(), mTempPaint);
            // copy back to canvas
            mTempRect.left = 0;
            mTempRect.right = mHighFadeShaderLength;
            canvas.translate(highEdge - mHighFadeShaderLength, 0);
            canvas.drawBitmap(tempBitmap, mTempRect, mTempRect, null);
            canvas.translate(-(highEdge - mHighFadeShaderLength), 0);
        }
    }
}


/*
 * Copyright (C) 2014 The Android Open Source Project.
 *
 *        [email protected]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.taihua.ckshop.util;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;



abstract class BaseGridView extends RecyclerView {

    /**
     * Always keep focused item at a aligned position.  Developer can use
     * WINDOW_ALIGN_XXX and ITEM_ALIGN_XXX to define how focused item is aligned.
     * In this mode, the last focused position will be remembered and restored when focus
     * is back to the view.
     */
    public final static int FOCUS_SCROLL_ALIGNED = 0;

    /**
     * Scroll to make the focused item inside client area.
     */
    public final static int FOCUS_SCROLL_ITEM = 1;

    /**
     * Scroll a page of items when focusing to item outside the client area.
     * The page size matches the client area size of RecyclerView.
     */
    public final static int FOCUS_SCROLL_PAGE = 2;

    /**
     * The first item is aligned with the low edge of the viewport. When
     * navigating away from the first item, the focus maintains a middle
     * location.
     * <p>
     * The middle location is calculated by "windowAlignOffset" and
     * "windowAlignOffsetPercent"; if neither of these two is defined, the
     * default value is 1/2 of the size.
     */
    public final static int WINDOW_ALIGN_LOW_EDGE = 1;

    /**
     * The last item is aligned with the high edge of the viewport when
     * navigating to the end of list. When navigating away from the end, the
     * focus maintains a middle location.
     * <p>
     * The middle location is calculated by "windowAlignOffset" and
     * "windowAlignOffsetPercent"; if neither of these two is defined, the
     * default value is 1/2 of the size.
     */
    public final static int WINDOW_ALIGN_HIGH_EDGE = 1 << 1;

    /**
     * The first item and last item are aligned with the two edges of the
     * viewport. When navigating in the middle of list, the focus maintains a
     * middle location.
     * <p>
     * The middle location is calculated by "windowAlignOffset" and
     * "windowAlignOffsetPercent"; if neither of these two is defined, the
     * default value is 1/2 of the size.
     */
    public final static int WINDOW_ALIGN_BOTH_EDGE =
            WINDOW_ALIGN_LOW_EDGE | WINDOW_ALIGN_HIGH_EDGE;

    /**
     * The focused item always stays in a middle location.
     * <p>
     * The middle location is calculated by "windowAlignOffset" and
     * "windowAlignOffsetPercent"; if neither of these two is defined, the
     * default value is 1/2 of the size.
     */
    public final static int WINDOW_ALIGN_NO_EDGE = 0;

    /**
     * Value indicates that percent is not used.
     */
    public final static float WINDOW_ALIGN_OFFSET_PERCENT_DISABLED = -1;

    /**
     * Value indicates that percent is not used.
     */
    public final static float ITEM_ALIGN_OFFSET_PERCENT_DISABLED = -1;

    protected final GridLayoutManager mLayoutManager;

    /**
     * Animate layout changes from a child resizing or adding/removing a child.
     */
    private boolean mAnimateChildLayout = true;

    private ItemAnimator mSavedItemAnimator;

    public BaseGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mLayoutManager = new GridLayoutManager(this);
        setLayoutManager(mLayoutManager);
        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
        setHasFixedSize(true);
        setChildrenDrawingOrderEnabled(true);
    }

    protected void initBaseGridViewAttributes(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.lbBaseGridView);
        boolean throughFront = a.getBoolean(R.styleable.lbBaseGridView_focusOutFront, false);
        boolean throughEnd = a.getBoolean(R.styleable.lbBaseGridView_focusOutEnd, false);
        mLayoutManager.setFocusOutAllowed(throughFront, throughEnd);
        mLayoutManager.setVerticalMargin(
                a.getDimensionPixelSize(R.styleable.lbBaseGridView_verticalMargin, 0));
        mLayoutManager.setHorizontalMargin(
                a.getDimensionPixelSize(R.styleable.lbBaseGridView_horizontalMargin, 0));
        if (a.hasValue(R.styleable.lbBaseGridView_android_gravity)) {
            setGravity(a.getInt(R.styleable.lbBaseGridView_android_gravity, Gravity.NO_GRAVITY));
        }
        a.recycle();
    }

    /**
     * Set the strategy used to scroll in response to item focus changing:
     * <ul>
     * <li>{@link #FOCUS_SCROLL_ALIGNED} (default) </li>
     * <li>{@link #FOCUS_SCROLL_ITEM}</li>
     * <li>{@link #FOCUS_SCROLL_PAGE}</li>
     * </ul>
     */
    public void setFocusScrollStrategy(int scrollStrategy) {
        if (scrollStrategy != FOCUS_SCROLL_ALIGNED && scrollStrategy != FOCUS_SCROLL_ITEM
            && scrollStrategy != FOCUS_SCROLL_PAGE) {
            throw new IllegalArgumentException("Invalid scrollStrategy");
        }
        mLayoutManager.setFocusScrollStrategy(scrollStrategy);
        requestLayout();
    }

    /**
     * Returns the strategy used to scroll in response to item focus changing.
     * <ul>
     * <li>{@link #FOCUS_SCROLL_ALIGNED} (default) </li>
     * <li>{@link #FOCUS_SCROLL_ITEM}</li>
     * <li>{@link #FOCUS_SCROLL_PAGE}</li>
     * </ul>
     */
    public int getFocusScrollStrategy() {
        return mLayoutManager.getFocusScrollStrategy();
    }

    /**
     * Set how the focused item gets aligned in the view.
     *
     * @param windowAlignment {@link #WINDOW_ALIGN_BOTH_EDGE},
     *        {@link #WINDOW_ALIGN_LOW_EDGE}, {@link #WINDOW_ALIGN_HIGH_EDGE} or
     *        {@link #WINDOW_ALIGN_NO_EDGE}.
     */
    public void setWindowAlignment(int windowAlignment) {
        mLayoutManager.setWindowAlignment(windowAlignment);
        requestLayout();
    }

    /**
     * Get how the focused item gets aligned in the view.
     *
     * @return {@link #WINDOW_ALIGN_BOTH_EDGE}, {@link #WINDOW_ALIGN_LOW_EDGE},
     *         {@link #WINDOW_ALIGN_HIGH_EDGE} or {@link #WINDOW_ALIGN_NO_EDGE}.
     */
    public int getWindowAlignment() {
        return mLayoutManager.getWindowAlignment();
    }

    /**
     * Set the absolute offset in pixels for window alignment.
     *
     * @param offset The number of pixels to offset. Can be negative for
     *        alignment from the high edge, or positive for alignment from the
     *        low edge.
     */
    public void setWindowAlignmentOffset(int offset) {
        mLayoutManager.setWindowAlignmentOffset(offset);
        requestLayout();
    }

    /**
     * Get the absolute offset in pixels for window alignment.
     *
     * @return The number of pixels to offset. Will be negative for alignment
     *         from the high edge, or positive for alignment from the low edge.
     *         Default value is 0.
     */
    public int getWindowAlignmentOffset() {
        return mLayoutManager.getWindowAlignmentOffset();
    }

    /**
     * Set offset percent for window alignment in addition to {@link
     * #getWindowAlignmentOffset()}.
     *
     * @param offsetPercent Percentage to offset. E.g., 40 means 40% of the
     *        width from low edge. Use
     *        {@link #WINDOW_ALIGN_OFFSET_PERCENT_DISABLED} to disable.
     */
    public void setWindowAlignmentOffsetPercent(float offsetPercent) {
        mLayoutManager.setWindowAlignmentOffsetPercent(offsetPercent);
        requestLayout();
    }

    /**
     * Get offset percent for window alignment in addition to
     * {@link #getWindowAlignmentOffset()}.
     *
     * @return Percentage to offset. E.g., 40 means 40% of the width from the 
     *         low edge, or {@link #WINDOW_ALIGN_OFFSET_PERCENT_DISABLED} if
     *         disabled. Default value is 50.
     */
    public float getWindowAlignmentOffsetPercent() {
        return mLayoutManager.getWindowAlignmentOffsetPercent();
    }

    /**
     * Set the absolute offset in pixels for item alignment.
     *
     * @param offset The number of pixels to offset. Can be negative for
     *        alignment from the high edge, or positive for alignment from the
     *        low edge.
     */
    public void setItemAlignmentOffset(int offset) {
        mLayoutManager.setItemAlignmentOffset(offset);
        requestLayout();
    }

    /**
     * Get the absolute offset in pixels for item alignment.
     *
     * @return The number of pixels to offset. Will be negative for alignment
     *         from the high edge, or positive for alignment from the low edge.
     *         Default value is 0.
     */
    public int getItemAlignmentOffset() {
        return mLayoutManager.getItemAlignmentOffset();
    }

    /**
     * Set to true if include padding in calculating item align offset.
     *
     * @param withPadding When it is true: we include left/top padding for positive
     *          item offset, include right/bottom padding for negative item offset.
     */
    public void setItemAlignmentOffsetWithPadding(boolean withPadding) {
        mLayoutManager.setItemAlignmentOffsetWithPadding(withPadding);
        requestLayout();
    }

    /**
     * Returns true if include padding in calculating item align offset.
     */
    public boolean isItemAlignmentOffsetWithPadding() {
        return mLayoutManager.isItemAlignmentOffsetWithPadding();
    }

    /**
     * Set offset percent for item alignment in addition to {@link
     * #getItemAlignmentOffset()}.
     *
     * @param offsetPercent Percentage to offset. E.g., 40 means 40% of the
     *        width from the low edge. Use
     *        {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED} to disable.
     */
    public void setItemAlignmentOffsetPercent(float offsetPercent) {
        mLayoutManager.setItemAlignmentOffsetPercent(offsetPercent);
        requestLayout();
    }

    /**
     * Get offset percent for item alignment in addition to {@link
     * #getItemAlignmentOffset()}.
     *
     * @return Percentage to offset. E.g., 40 means 40% of the width from the
     *         low edge, or {@link #ITEM_ALIGN_OFFSET_PERCENT_DISABLED} if
     *         disabled. Default value is 50.
     */
    public float getItemAlignmentOffsetPercent() {
        return mLayoutManager.getItemAlignmentOffsetPercent();
    }

    /**
     * Set the id of the view to align with. Use zero (default) for the item
     * view itself.
     */
    public void setItemAlignmentViewId(int viewId) {
        mLayoutManager.setItemAlignmentViewId(viewId);
    }

    /**
     * Get the id of the view to align with, or zero for the item view itself.
     */
    public int getItemAlignmentViewId() {
        return mLayoutManager.getItemAlignmentViewId();
    }

    /**
     * Set the margin in pixels between two child items.
     */
    public void setItemMargin(int margin) {
        mLayoutManager.setItemMargin(margin);
        requestLayout();
    }

    /**
     * Set the margin in pixels between two child items vertically.
     */
    public void setVerticalMargin(int margin) {
        mLayoutManager.setVerticalMargin(margin);
        requestLayout();
    }

    /**
     * Get the margin in pixels between two child items vertically.
     */
    public int getVerticalMargin() {
        return mLayoutManager.getVerticalMargin();
    }

    /**
     * Set the margin in pixels between two child items horizontally.
     */
    public void setHorizontalMargin(int margin) {
        mLayoutManager.setHorizontalMargin(margin);
        requestLayout();
    }

    /**
     * Get the margin in pixels between two child items horizontally.
     */
    public int getHorizontalMargin() {
        return mLayoutManager.getHorizontalMargin();
    }

    /**
     * Register a callback to be invoked when an item in BaseGridView has
     * been selected.
     */
    public void setOnChildSelectedListener(OnChildSelectedListener listener) {
        mLayoutManager.setOnChildSelectedListener(listener);
    }

    /**
     * Change the selected item immediately without animation.
     */
    public void setSelectedPosition(int position) {
        mLayoutManager.setSelection(this, position);
    }

    /**
     * Change the selected item and run an animation to scroll to the target
     * position.
     */
    public void setSelectedPositionSmooth(int position) {
        mLayoutManager.setSelectionSmooth(this, position);
    }

    /**
     * Get the selected item position.
     */
    public int getSelectedPosition() {
        return mLayoutManager.getSelection();
    }

    /**
     * Set if an animation should run when a child changes size or when adding
     * or removing a child.
     * <p><i>Unstable API, might change later.</i>
     */
    public void setAnimateChildLayout(boolean animateChildLayout) {
        if (mAnimateChildLayout != animateChildLayout) {
            mAnimateChildLayout = animateChildLayout;
            if (!mAnimateChildLayout) {
                mSavedItemAnimator = getItemAnimator();
                super.setItemAnimator(null);
            } else {
                super.setItemAnimator(mSavedItemAnimator);
            }
        }
    }

    /**
     * Return true if an animation will run when a child changes size or when
     * adding or removing a child.
     * <p><i>Unstable API, might change later.</i>
     */
    public boolean isChildLayoutAnimated() {
        return mAnimateChildLayout;
    }

    /**
     * Describes how the child views are positioned. Defaults to
     * GRAVITY_TOP|GRAVITY_LEFT.
     *
     * @param gravity See {@link Gravity}
     */
    public void setGravity(int gravity) {
        mLayoutManager.setGravity(gravity);
        requestLayout();
    }

    @Override
    public void setDescendantFocusability (int focusability) {
        // enforce FOCUS_AFTER_DESCENDANTS
        super.setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
    }

    @Override
    public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
        return mLayoutManager.gridOnRequestFocusInDescendants(this, direction,
                previouslyFocusedRect);
    }

    /**
     * Get the x/y offsets to final position from current position if the view
     * is selected.
     *
     * @param view The view to get offsets.
     * @param offsets offsets[0] holds offset of X, offsets[1] holds offset of
     *        Y.
     */
    public void getViewSelectedOffsets(View view, int[] offsets) {
        mLayoutManager.getViewSelectedOffsets(view, offsets);
    }

    @Override
    public int getChildDrawingOrder(int childCount, int i) {
        return mLayoutManager.getChildDrawingOrder(this, childCount, i);
    }

    final boolean isChildrenDrawingOrderEnabledInternal() {
        return isChildrenDrawingOrderEnabled();
    }

    /**
     * Disable or enable focus search.
     */
    public final void setFocusSearchDisabled(boolean disabled) {
        mLayoutManager.setFocusSearchDisabled(disabled);
    }

    /**
     * Return true if focus search is disabled.
     */
    public final boolean isFocusSearchDisabled() {
        return mLayoutManager.isFocusSearchDisabled();
    }

    /**
     * Enable or disable layout.  All children will be removed when layout is
     * disabled.
     */
    public void setLayoutEnabled(boolean layoutEnabled) {
        mLayoutManager.setLayoutEnabled(layoutEnabled);
    }

    /**
     * Enable or disable pruning child.  Disable is useful during transition.
     */
    public void setPruneChild(boolean pruneChild) {
        mLayoutManager.setPruneChild(pruneChild);
    }

    /**
     * Returns true if the view at the given position has a same row sibling
     * in front of it.
     *
     * @param position Position in adapter.
     */
    public boolean hasPreviousViewInSameRow(int position) {
        return mLayoutManager.hasPreviousViewInSameRow(position);
    }


}
接下來是使用方法
holder.mHorizontalGridView.setAdapter(new RecyclerView.Adapter() {
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
                ImageView iv = new ImageView(context);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                iv.setScaleType(ImageView.ScaleType.FIT_XY);
                iv.setLayoutParams(lp);
                iv.setMinimumWidth(300);
                iv.setMaxWidth(300);
                MyApp.bitmapUtils.display(iv, pictureList.get(i));
                final RecyclerView.ViewHolder viewHolder = new RecyclerView.ViewHolder(iv);
                //TODO 把Item的點選事件在這裡做,呼叫View.setOnClickListener(View.OnClickListener),然後用viewHoder.getPosition()來獲取點選的位置
                //以同樣的方法可以實現OnLongClickListener等
                //注意:RecyclerView.ViewHolder不能直接新增監聽,可以用RecyclerView.ViewHolder.itemView新增監聽
                viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent = new Intent(context, EvaluatePictureActivity.class);
                        intent.putStringArrayListExtra("largePictureList", (ArrayList<String>) largePictureList);
                        context.startActivity(intent);
                    }
                });
                return viewHolder;
            }

            @Override
            public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
                //TODO 把一些View的相關改變在這裡實現
            }

            @Override
            public int getItemCount() {
                return pictureList.size();
            }
        });