折叠式侧滑菜单

来源:互联网 发布:php xss攻击防御 编辑:程序博客网 时间:2024/04/30 14:57

1,利用canvas.concat(Matric);使得图片折叠

2,利用Canvas.clipRect(...);截取需要的部分

3,利用Paint.setShaper(LinearGradient);绘制阴影

4,与DrawerLayout与SlidingPanelLayout结合,形成折叠式侧滑菜单

package com.wang.simple_foldinglayout.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.Shader.TileMode;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;public class FlodLayout extends ViewGroup {// 总的块数private final static int NUM_OF_FLOD = 8;// 原图的宽度private float mFlodWidth;// 折叠后的宽度private float mTranslateDis;// 原图每一块的宽度private float mWidthPerFlod;// 折叠后每一块的宽度private float mTranslateDisPerFlod;// 绘制阴暗区的画笔对象private Paint mSoildPaint;// 绘制阴影部分的画笔private Paint mShadowPaint;private LinearGradient mShadowGradientShader;private Matrix mShadowMatrix;// 缩放的比例private float mFactor = 1.0f;// 获取,容器里面的视图private Bitmap mBitmap;private Canvas mCanvas = new Canvas();private boolean isready = false;private Matrix[] mMatrix = new Matrix[NUM_OF_FLOD];public FlodLayout(Context context) {this(context, null, 0);}public FlodLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public FlodLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mSoildPaint = new Paint();mShadowPaint = new Paint();mShadowPaint.setStyle(Style.FILL);mShadowGradientShader = new LinearGradient(0, 0, 0.5f, 0, Color.BLACK,Color.TRANSPARENT, TileMode.CLAMP);mShadowPaint.setShader(mShadowGradientShader);mShadowMatrix = new Matrix();// 先生成对象for (int i = 0; i < NUM_OF_FLOD; i++) {mMatrix[i] = new Matrix();}setWillNotDraw(false);}/** * 调整控件的高宽 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {View child = getChildAt(0);measureChild(child, widthMeasureSpec, heightMeasureSpec);setMeasuredDimension(child.getMeasuredWidth(),child.getMeasuredHeight());}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {View child = getChildAt(0);child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());mBitmap = Bitmap.createBitmap(child.getMeasuredWidth(),child.getMeasuredHeight(), Config.ARGB_8888);mCanvas.setBitmap(mBitmap);updateFlod();}private void updateFlod() {int w = getMeasuredWidth();int h = getMeasuredHeight();// 未折叠时的宽度mFlodWidth = w;// Log.i("wangsongbin", "w:"+w+" mFlodWidth:"+mFlodWidth);// 折叠后的宽度mTranslateDis = w * mFactor;// 未折叠时没快的宽度mWidthPerFlod = w / NUM_OF_FLOD;// 折叠后每块的宽度mTranslateDisPerFlod = mTranslateDis / NUM_OF_FLOD;int alpha = (int) (255 * (1 - mFactor));mSoildPaint.setColor(Color.argb((int) (alpha * 0.8f), 0, 0, 0));mShadowMatrix.setScale(mWidthPerFlod, 1);mShadowGradientShader.setLocalMatrix(mShadowMatrix);mShadowPaint.setAlpha(alpha);float[] src = new float[8];float[] dst = new float[8];boolean isEven;int depth = (int) (Math.sqrt(mWidthPerFlod * mWidthPerFlod- mTranslateDisPerFlod * mTranslateDisPerFlod) / 2);// 初始化for (int i = 0; i < NUM_OF_FLOD; i++) {mMatrix[i].reset();src[0] = i * mWidthPerFlod;src[1] = 0;src[2] = src[0] + mWidthPerFlod;src[3] = src[1];src[4] = src[2];src[5] = getMeasuredHeight();src[6] = src[0];src[7] = src[5];isEven = i % 2 == 0;dst[0] = i * mTranslateDisPerFlod;dst[1] = isEven ? 0 : depth;dst[2] = dst[0] + mTranslateDisPerFlod;dst[3] = isEven ? depth : 0;dst[4] = dst[2];dst[5] = isEven ? getMeasuredHeight() - depth : getMeasuredHeight();dst[6] = dst[0];dst[7] = isEven ? getMeasuredHeight() : getMeasuredHeight() - depth;if(mTranslateDis>10){//四舍五入是为了防止中间出现白线都转化为整数for (int j = 0; j < dst.length; j++) {dst[j] = Math.round(dst[j]);}}mMatrix[i].setPolyToPoly(src, 0, dst, 0, NUM_OF_FLOD >> 1);}}@Overrideprotected void dispatchDraw(Canvas canvas) {if (mFactor == 0) {return;} else if (mFactor == 1) {super.dispatchDraw(canvas);return;}for (int i = 0; i < 8; i++) {canvas.save();canvas.concat(mMatrix[i]);// 控制需要绘制的大小canvas.clipRect(i * mWidthPerFlod, 0, (i + 1) * mWidthPerFlod,getMeasuredHeight());// 把容器视图取出,就不同每次都调用super.dispatchDraw()方法if (isready) {canvas.drawBitmap(mBitmap, 0, 0, null);} else {// 获得容器里面的视图super.dispatchDraw(mCanvas);canvas.drawBitmap(mBitmap, 0, 0, null);//isready = true;}// 绘制阴面和阴影canvas.translate(mWidthPerFlod * i, 0);if (i % 2 == 0) {canvas.drawRect(0, 0, mWidthPerFlod, getMeasuredHeight(),mSoildPaint);} else {canvas.drawRect(0, 0, mWidthPerFlod, getMeasuredHeight(),mShadowPaint);}canvas.restore();}}public void setFator(float mFactor) {this.mFactor = mFactor;updateFlod();invalidate();}}
与DrawerLayout结合

package com.wang.simple_foldinglayout.view;import android.content.Context;import android.support.v4.view.GravityCompat;import android.support.v4.view.ViewCompat;import android.support.v4.widget.DrawerLayout;import android.util.AttributeSet;import android.util.Log;import android.view.Gravity;import android.view.View;public class FlodDrawerLayout extends DrawerLayout {public FlodDrawerLayout(Context context) {super(context);}public FlodDrawerLayout(Context context, AttributeSet attrs) {super(context, attrs);}public FlodDrawerLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();// 获得子控件的数量int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View child = getChildAt(i);// 判断child是否有layout_gravity属性if (isDraverView(child)) {FlodLayout flodLayout = new FlodLayout(getContext());removeView(child);android.view.ViewGroup.LayoutParams lp = child.getLayoutParams();flodLayout.addView(child);addView(flodLayout, i, lp);}}//注册监听器setDrawerListener(new DrawerListener() {@Overridepublic void onDrawerStateChanged(int arg0) {// TODO Auto-generated method stub}@Overridepublic void onDrawerSlide(View drawerview, float slideOffset) {Log.i("wangsongbin", slideOffset+"");if(drawerview instanceof FlodLayout){FlodLayout flodLayout=(FlodLayout) drawerview;flodLayout.setFator(slideOffset);}}@Overridepublic void onDrawerOpened(View arg0) {// TODO Auto-generated method stub}@Overridepublic void onDrawerClosed(View arg0) {// TODO Auto-generated method stub}});}private boolean isDraverView(View child) {LayoutParams lp = (LayoutParams) child.getLayoutParams();//这时得到的gravity不是通用的int gravity = lp.gravity;//Log.i("wangsongbin", "" + gravity);//标准的gravity值int absGravity = GravityCompat.getAbsoluteGravity(gravity,ViewCompat.getLayoutDirection(child));//Log.i("wangsongbin", "" + absGravity);return (absGravity & (Gravity.LEFT | Gravity.RIGHT)) != 0;}}
与SlidingPanelLayout结合

package com.wang.simple_foldinglayout.view;import android.content.Context;import android.support.v4.widget.SlidingPaneLayout;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;public class FlodSlidingPaneLayout extends SlidingPaneLayout {public FlodSlidingPaneLayout(Context context) {super(context);}public FlodSlidingPaneLayout(Context context, AttributeSet attrs) {super(context, attrs);}public FlodSlidingPaneLayout(Context context, AttributeSet attrs,int defStyle) {super(context, attrs, defStyle);}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();// 获得一个子元素,即菜单列表控件View child = getChildAt(0);if (child != null) {// 移除他,removeView(child);// 包上我的自定义的布局后再加进去final FlodLayout flodLayout = new FlodLayout(getContext());flodLayout.addView(child);ViewGroup.LayoutParams lp = child.getLayoutParams();addView(flodLayout, 0, lp);//注册监听器setPanelSlideListener(new PanelSlideListener() {@Overridepublic void onPanelSlide(View arg0, float arg1) {flodLayout.setFator(arg1);}@Overridepublic void onPanelOpened(View arg0) {// TODO Auto-generated method stub}@Overridepublic void onPanelClosed(View arg0) {// TODO Auto-generated method stub}});}}}

源码下载



0 0