1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
| public class MenuDecoration extends SpacesItemDecoration { private static final int NOT_FOUND_SPAN_SIZE = -1; private static int MENU_TITLE_SPAN_SIZE = 3; private final int shadowSize=2; private float radius = 30; private int color = Color.RED; private boolean needTop; public static final int TYPE_GROUP_DATA = 1; public static final int TYPE_MENU_GROUP_NAME = 0;
/** * @param recyclerView * @param spanCount * @param needLeft * @param needRight * @param isneddTop */ public MenuDecoration(RecyclerView recyclerView, int spanCount, boolean needLeft, boolean needRight, boolean isneddTop, int space, float radius, int color) {
super((int) (space)); this.radius = radius; this.color = color; GridLayoutManager layoutManager = new GridLayoutManager(recyclerView.getContext(), spanCount, LinearLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(layoutManager);
layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int type = recyclerView.getAdapter().getItemViewType(position); if (position >= recyclerView.getAdapter().getItemCount()) { return NOT_FOUND_SPAN_SIZE; } else if (type == TYPE_MENU_GROUP_NAME) { return MENU_TITLE_SPAN_SIZE; } else if (type == TYPE_GROUP_DATA) { return 1; } else { return NOT_FOUND_SPAN_SIZE;//这是 decoration调用的。 } }
@Override public int getSpanIndex(int position, int spanCount) { int spanIndex = super.getSpanIndex(position, spanCount); Log.w(TAG, "spanIndex" + spanIndex + ",pos" + position + ",spanCount:" + spanCount); return spanIndex; }
@Override public int getSpanGroupIndex(int adapterPosition, int spanCount) { int spanGroupIndex = super.getSpanGroupIndex(adapterPosition, spanCount); Log.w(TAG, "spanGroupIndex" + spanGroupIndex + ",adapterPosition" + adapterPosition + ",spanCount:" + spanCount); return spanGroupIndex; } }); /** * 顶部 下面实现了 */ this.needTop = isneddTop; MENU_TITLE_SPAN_SIZE = spanCount; recyclerView.setPadding(needLeft ? getSpace() : 0, isneddTop ? getSpace() / 2 : 0, needRight ? getSpace() : 0, getSpace() / 2); }
private static final String TAG = "Gridlayout";
@Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
// int itemCount = parent.getLayoutManager().getItemCount(); int childAdapterPosition = parent.getChildAdapterPosition(view); GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager(); int spanCount = layoutManager.getSpanCount(); //构造时传递的参数. //DefaultSpanSizeLookup int spanSize = layoutManager.getSpanSizeLookup().getSpanSize(childAdapterPosition); int spanGroupIndex = layoutManager.getSpanSizeLookup().getSpanGroupIndex(childAdapterPosition, spanCount);
if (spanSize == MENU_TITLE_SPAN_SIZE) { //标题才跨 3个。 // if (needTop) { if (spanGroupIndex == 0) { outRect.top = (int) (getSpace() + radius); } else { outRect.top = (int) (getSpace() + (radius*2)); } // } } else { outRect.top = 0; outRect.left = 0; outRect.right = 0; if( spanGroupIndex==0){//没有头部 的顶 outRect.top = (int) (getSpace() + radius); }else{ outRect.top = 0; } int spanIndex = layoutManager.getSpanSizeLookup().getSpanIndex(childAdapterPosition, spanCount); //比如第一个是标题 ,第二列是 3格子,标题的永远是0 ,分3列的则是0 12 这样的循环。groupindex就是 每一列的完毕 就算一组。 int itemCount = parent.getLayoutManager().getItemCount(); int lastspanIndex = layoutManager.getSpanSizeLookup().getSpanIndex(itemCount-1, spanCount); //比如第一个是标题 ,第二列是 3格子,标题的永远是0 ,分3列的则是0 12 这样的循环。groupindex就是 每一列的完毕 就算一组。
if (childAdapterPosition>=itemCount-(lastspanIndex+1)) {//最后一行 outRect.bottom= (int) (getSpace()+(radius/2)); if(lastspanIndex==spanIndex&&(1+spanIndex!=MENU_TITLE_SPAN_SIZE)){ // outRect.right=30;//=parent.getRight()-parent.getPaddingRight();//写不写其实都一样,因为不绘制右边?不,应该说都铺满屏幕了,不怕控件没给够 }//不能加right,会影响空间 }
}
if (BuildConfig.DEBUG) { // int spanGroupIndex =;//1 23格子 或者 1列 都算一组, int spanIndex = layoutManager.getSpanSizeLookup().getSpanIndex(childAdapterPosition, spanCount); //比如第一个是标题 ,第二列是 3格子,标题的永远是0 ,分3列的则是0 12 这样的循环。groupindex就是 每一列的完毕 就算一组。 /* SubMenuItemI subMenuItemI = ((MyAppListAdapter) parent.getAdapter()).getData().get(childAdapterPosition); String title = subMenuItemI.getTitle();*/ Log.w(TAG, "Decoration SpanIndex:" + spanIndex + ",groupindex:" + spanGroupIndex + ",spanSize:" + spanSize + ",model:" + "title" + ",adapterposition:" + childAdapterPosition);
} }
@Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { // public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { doDraw(c, parent); }
private void doDraw(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); Drawable drawable; for (int ix = 0; ix < childCount; ix++) { final View child = parent.getChildAt(ix); /* if (true) {
debugDrwa(c, left, right, child); continue; }*/ int position = parent.getChildAdapterPosition(child); // parent.getChildLayoutPosition() GridLayoutManager layoutManager = (GridLayoutManager) parent.getLayoutManager(); int spanCount = layoutManager.getSpanCount();//表示整个列表分多少列 int spanSize = layoutManager.getSpanSizeLookup().getSpanSize(position);//表示当前格所占有的格子数 int spanIndex = layoutManager.getSpanSizeLookup().getSpanIndex(position, spanCount); //这里参数是spanCount,不是spanSize,否则不对,比如第一个是标题 ,第二列是 3格子,标题的永远是0 ,分3列的则是0 12 这样的循环。groupindex就是 每一列的完毕 就算一组。
if (BuildConfig.DEBUG) { // MyAppListAdapter adapter = (MyAppListAdapter) parent.getAdapter(); // SubMenuItemI subMenuItemI = adapter.getData().get(position); // int spanSizeNext = layoutManager.getSpanSizeLookup().getSpanSize(position + 1); }
if (spanSize != MENU_TITLE_SPAN_SIZE) {//普通item只会跨1个。 除非是菜单 int spanGroupIndex = layoutManager.getSpanSizeLookup().getSpanGroupIndex(position, spanCount); int spanSizeNext = layoutManager.getSpanSizeLookup().getSpanSize(position + 1); if (spanIndex < MENU_TITLE_SPAN_SIZE - 1) {// MENU_TITLE_SPAN_SIZE 等于new GridManager里面的Count,这里用合并的数来判断也可以做,是否属于最后一个格子,但是最后一个格子又是否铺满整个屏幕是最后一个但是没有刚好没铺满,就把它给铺满。 if (spanSizeNext == NOT_FOUND_SPAN_SIZE || spanSizeNext == MENU_TITLE_SPAN_SIZE) {//如果下一个不存在那么是最后一个,或者下一个是标题了。 drawable = generateDrawable(-1);//补空缺 boundAndDraw(c, child.getRight(), right, drawable, child.getTop(), child.getBottom());//这里没有任何圆角 if (BuildConfig.DEBUG) { /* MyAppListAdapter adapter = (MyAppListAdapter) parent.getAdapter(); SubMenuItemI subMenuItemI = adapter.getData().get(position); Log.w(TAG, subMenuItemI + ",为最后一个前后面超出!spanIndex:" + spanIndex + ",spanSize:" + spanSize + ",height:" + child.getHeight()); */ }
} }
if (spanSizeNext == NOT_FOUND_SPAN_SIZE || spanSizeNext == MENU_TITLE_SPAN_SIZE) {// 刚好铺满的那种 铺满还需要判断是否下一行是否是标题. //左下角圆角. drawable = generateDrawable(5);//,spanSizeNext == NOT_FOUND_SPAN_SIZE ?Color.GREEN:Color.YELLOW); int top = child.getTop() + child.getHeight(); int bottom = (int) (top + radius); // Log.w(TAG,"LEFT:"+left+",top:"+top+",right:"+right+",bottom:"+bottom); boundAndDraw(c, left, right, drawable, top, bottom); } if( spanGroupIndex==0&&position==0){//没有头部 的顶 drawable = generateDrawable(4); int top = (int) (child.getTop() - radius); int bottom = child.getTop(); boundAndDraw(c, left, right, drawable, top, bottom); }
} else {//标题头 drawable = generateDrawable(4); int top = (int) (child.getTop() - radius); int bottom = child.getTop(); boundAndDraw(c, left, right, drawable, top, bottom); } } }
private void debugDrwa(Canvas c, int left, int right, View child) { //以下计算主要用来确定绘制的位置 final int top1 = child.getBottom() + 1; ColorDrawable drawable1 = new ColorDrawable(Color.BLUE); final int bottom = top1 + drawable1.getIntrinsicHeight(); boundAndDraw(c, left, right, drawable1, top1, bottom); }
private void boundAndDraw(Canvas c, int left, int right, Drawable drawable, int top, int bottom) { // Log.w(TAG,"DrawCall LEFT:"+left+",righ:"+right+",top:"+top+",bottom:"+bottom); drawable.setBounds(left, top, right, bottom); // drawable.setBounds(left, (int) (child.getTop()+child.getHeight()-radius), left + child.getWidth(), child.getBottom()); drawable.draw(c); }
/** * /外矩形 0左上、1右上、2 右下、3左下的圆角半 4 上 左和右边 5 ,下 左右。 * * @param type * @return */ private Drawable generateDrawable(int type, int color) { this.color = color; return generateDrawable(type); }
private Drawable generateDrawable(int type) {
GradientDrawable gd = new GradientDrawable(); // color=color|0xff000000;
gd.setColor(color); switch (type) { case 0: gd.setCornerRadii(new float[]{radius, radius, 0, 0, 0, 0, 0, 0}); break; case 1: gd.setCornerRadii(new float[]{0, 0, radius, radius, 0, 0, 0, 0}); break; case 2: gd.setCornerRadii(new float[]{0, 0, 0, 0, radius, radius, 0, 0}); break; case 3: gd.setCornerRadii(new float[]{0, 0, 0, 0, 0, 0, radius, radius}); break; case 4: gd.setCornerRadii(new float[]{radius, radius, radius, radius, 0, 0, 0, 0}); break; case 5: gd.setCornerRadii(new float[]{0, 0, 0, 0, radius, radius, radius, radius}); break; case 6: gd.setCornerRadii(new float[]{radius, radius, radius, radius, radius, radius, radius, radius}); break; default: gd.setCornerRadii(new float[]{0, 0, 0, 0, 0, 0, 0, 0}); break; } /* Drawable[] drawables=new Drawable[2]; GradientDrawable gdshadow = new GradientDrawable();
//#ffdb8f #ffdb8f gdshadow.setColor(Color.parseColor("#00ff00")); drawables[0]=gdshadow; drawables[1]=gd; LayerDrawable layerDrawable=new LayerDrawable(drawables);
*/
return gd; }
|