Java tutorial
/* * Copyright (C) 2016 The Android Open Source Project * * 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.ziv.recyclerview.gridview.vertical; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; import android.support.v4.view.ViewCompat; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.LinearLayout; /** * RecyclerView?item???Divider?? * {@link DividerItemDecoration} * Created by ziv on 16-11-30. */ public class DividerGridItemDecoration extends RecyclerView.ItemDecoration { public static final int HORIZONTAL = LinearLayout.HORIZONTAL; public static final int VERTICAL = LinearLayout.VERTICAL; private static final int[] ATTRS = new int[] { android.R.attr.listDivider }; private final Rect mBounds = new Rect(); private Drawable mDivider; /** * Current orientation. Either {@link #HORIZONTAL} or {@link #VERTICAL}. */ private int mOrientation; /** * Creates a divider, default orientation is {@link #VERTICAL}. * * @param context Current context, it will be used to access resources. */ public DividerGridItemDecoration(Context context) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(VERTICAL); } /** * Creates a divider * * @param context Current context, it will be used to access resources. * @param orientation Divider orientation. Should be {@link #HORIZONTAL} or {@link #VERTICAL}. */ public DividerGridItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } /** * Sets the orientation for this divider. * * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL} */ public void setOrientation(int orientation) { if (orientation != HORIZONTAL && orientation != VERTICAL) { throw new IllegalArgumentException("Invalid orientation. It should be either HORIZONTAL or VERTICAL"); } mOrientation = orientation; } /** * Sets the {@link Drawable} for this divider. * * @param drawable Drawable that should be used as a divider. */ public void setDrawable(@NonNull Drawable drawable) { if (drawable == null) { throw new IllegalArgumentException("Drawable cannot be null."); } mDivider = drawable; } /** * Draw any appropriate decorations into the Canvas supplied to the RecyclerView. * * <p> * {@link RecyclerView.ItemDecoration#onDraw(Canvas, RecyclerView, RecyclerView.State)} * * @param c Canvas to draw into * @param parent RecyclerView this ItemDecoration is drawing into * @param state The current state of RecyclerView */ @Override @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { if (parent.getLayoutManager() == null) { throw new IllegalArgumentException("RecyclerView should have an LayoutManager."); } if (mOrientation == VERTICAL) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } /** * Draw vertical divider * * @param canvas Canvas to draw into * @param parent RecyclerView this ItemDecoration is drawing into */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void drawVertical(Canvas canvas, RecyclerView parent) { canvas.save(); final int left; final int right; if (parent.getClipToPadding()) { left = parent.getPaddingLeft(); right = parent.getWidth() - parent.getPaddingRight(); canvas.clipRect(left, parent.getPaddingTop(), right, parent.getHeight() - parent.getPaddingBottom()); } else { left = 0; right = parent.getWidth(); } final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); parent.getDecoratedBoundsWithMargins(child, mBounds); final int bottom = mBounds.bottom + Math.round(ViewCompat.getTranslationY(child)); final int top = bottom - mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(canvas); } canvas.restore(); } /** * Draw horizontal divider * * @param canvas Canvas to draw into * @param parent RecyclerView this ItemDecoration is drawing into */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private void drawHorizontal(Canvas canvas, RecyclerView parent) { canvas.save(); final int top; final int bottom; if (parent.getClipToPadding()) { top = parent.getPaddingTop(); bottom = parent.getHeight() - parent.getPaddingBottom(); canvas.clipRect(parent.getPaddingLeft(), top, parent.getWidth() - parent.getPaddingRight(), bottom); } else { top = 0; bottom = parent.getHeight(); } final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); parent.getLayoutManager().getDecoratedBoundsWithMargins(child, mBounds); final int right = mBounds.right + Math.round(ViewCompat.getTranslationX(child)); final int left = right - mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(canvas); } canvas.restore(); } // /** // * ?? // * // * @param parent // * @param pos // * @param spanCount // * @param childCount // * @return // */ // private boolean isLastColum(RecyclerView parent, int pos, int spanCount, // int childCount) { // if (parent.getLayoutManager() == null) { // throw new IllegalArgumentException("RecyclerView should have an LayoutManager."); // } else { // LayoutManager layoutManager = parent.getLayoutManager(); // } // if (layoutManager instanceof GridLayoutManager) { // if ((pos + 1) % spanCount == 0)// ???? // { // return true; // } // } else if (layoutManager instanceof StaggeredGridLayoutManager) { // int orientation = ((StaggeredGridLayoutManager) layoutManager) // .getOrientation(); // if (orientation == StaggeredGridLayoutManager.VERTICAL) { // if ((pos + 1) % spanCount == 0)// ???? // { // return true; // } // } else { // childCount = childCount - childCount % spanCount; // if (pos >= childCount)// ???? // return true; // } // } // return false; // } // // /** // * ?? // * // * @param parent // * @param pos // * @param spanCount // * @param childCount // * @return // */ // private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, // int childCount) { // LayoutManager layoutManager = parent.getLayoutManager(); // if (layoutManager instanceof GridLayoutManager) { // childCount = childCount - childCount % spanCount; // if (pos >= childCount)// ??? // return true; // } else if (layoutManager instanceof StaggeredGridLayoutManager) { // int orientation = ((StaggeredGridLayoutManager) layoutManager) // .getOrientation(); // // StaggeredGridLayoutManager ? // if (orientation == StaggeredGridLayoutManager.VERTICAL) { // childCount = childCount - childCount % spanCount; // // ??? // if (pos >= childCount) // return true; // } else // // StaggeredGridLayoutManager ? // { // // ??? // if ((pos + 1) % spanCount == 0) { // return true; // } // } // } // return false; // } /** * ??item??? * {@link RecyclerView.ItemDecoration#getItemOffsets(Rect, View, RecyclerView, RecyclerView.State)} * * @param outRect Rect to receive the output. * @param view The child view to decorate * @param parent RecyclerView this ItemDecoration is decorating * @param state The current state of RecyclerView. */ @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { // int spanCount = getSpanCount(parent); // int childCount = parent.getAdapter().getItemCount(); if (mOrientation == VERTICAL) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } }