Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

liujiangyao лет назад: 7
Родитель
Сommit
5d6e4d1b2e

+ 2 - 0
app/build.gradle

@@ -126,6 +126,8 @@ repositories {
 }
 
 dependencies {
+    //noinspection GradleCompatible
+    compile 'com.android.support:cardview-v7:28.0.0-rc01'
     compile "com.android.support:design:$supportLibVersion"
     compile 'com.android.support.constraint:constraint-layout:1.0.2'
     testCompile 'junit:junit:4.12'

+ 58 - 0
app/src/main/java/com/kfzs/duanduan/cardview/BitmapUtils.java

@@ -0,0 +1,58 @@
+package com.kfzs.duanduan.cardview;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+public class BitmapUtils {
+    public static int MIN_WIDTH = 100;
+
+    /**
+     * 按最大边按一定大小缩放图片
+     *
+     * @param resources
+     * @param resId
+     * @param maxSize 压缩后最大长度
+     * @return
+     */
+    public static Bitmap scaleImage(Resources resources, int resId, int maxSize) {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;
+        BitmapFactory.decodeResource(resources, resId, options);
+        options.inSampleSize = calculateInSampleSize(options, maxSize, maxSize);
+        options.inJustDecodeBounds = false;
+
+        return BitmapFactory.decodeResource(resources, resId, options);
+    }
+
+    /**
+     * 计算inSampleSize
+     * @param options
+     * @param reqWidth
+     * @param reqHeight
+     * @return
+     */
+    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
+        int height = options.outHeight;
+        int width = options.outWidth;
+        int inSampleSize = 1;
+        if (width < MIN_WIDTH) {
+            return inSampleSize;
+        } else {
+            int heightRatio;
+            if (width > height && reqWidth < reqHeight || width < height && reqWidth > reqHeight) {
+                heightRatio = reqWidth;
+                reqWidth = reqHeight;
+                reqHeight = heightRatio;
+            }
+
+            if (height > reqHeight || width > reqWidth) {
+                heightRatio = Math.round((float) height / (float) reqHeight);
+                int widthRatio = Math.round((float) width / (float) reqWidth);
+                inSampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;
+            }
+
+            return inSampleSize;
+        }
+    }
+}

+ 74 - 0
app/src/main/java/com/kfzs/duanduan/cardview/BlurBitmapUtils.java

@@ -0,0 +1,74 @@
+package com.kfzs.duanduan.cardview;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.widget.ImageView;
+
+/**
+ * RenderScript图片高斯模糊
+ * Created by jameson on 9/2/16.
+ */
+public class BlurBitmapUtils {
+    /**
+     * 建议模糊度(在0.0到25.0之间)
+     */
+    private static final int BLUR_RADIUS = 20;
+    private static final int SCALED_WIDTH = 100;
+    private static final int SCALED_HEIGHT = 100;
+
+    public static void blur(ImageView imageView, Bitmap bitmap) {
+        blur(imageView, bitmap, BLUR_RADIUS);
+    }
+
+    public static void blur(ImageView imageView, Bitmap bitmap, int radius) {
+        imageView.setImageBitmap(getBlurBitmap(imageView.getContext(), bitmap, radius));
+    }
+
+    public static Bitmap getBlurBitmap(Context context, Bitmap bitmap) {
+        return getBlurBitmap(context, bitmap, BLUR_RADIUS);
+    }
+
+    /**
+     * 得到模糊后的bitmap
+     * thanks http://wl9739.github.io/2016/07/14/教你一分钟实现模糊效果/
+     *
+     * @param context
+     * @param bitmap
+     * @param radius
+     * @return
+     */
+    public static Bitmap getBlurBitmap(Context context, Bitmap bitmap, int radius) {
+        // 将缩小后的图片做为预渲染的图片。
+        Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, SCALED_WIDTH, SCALED_HEIGHT, false);
+        // 创建一张渲染后的输出图片。
+        Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
+
+        // 创建RenderScript内核对象
+        RenderScript rs = RenderScript.create(context);
+        // 创建一个模糊效果的RenderScript的工具对象
+        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
+
+        // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间。
+        // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去。
+        Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
+        Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
+
+        // 设置渲染的模糊程度, 25f是最大模糊度
+        blurScript.setRadius(radius);
+        // 设置blurScript对象的输入内存
+        blurScript.setInput(tmpIn);
+        // 将输出数据保存到输出内存中
+        blurScript.forEach(tmpOut);
+
+        // 将数据填充到Allocation中
+        tmpOut.copyTo(outputBitmap);
+
+        return outputBitmap;
+    }
+
+}

+ 61 - 0
app/src/main/java/com/kfzs/duanduan/cardview/CardAdapter.java

@@ -0,0 +1,61 @@
+package com.kfzs.duanduan.cardview;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.sheep.jiuyan.samllsheep.R;
+import com.sheep.jiuyan.samllsheep.utils.G;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Created by jameson on 8/30/16.
+ */
+public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {
+    private List<Integer> mList = new ArrayList<>();
+    private CardAdapterHelper mCardAdapterHelper = new CardAdapterHelper();
+
+    public CardAdapter(List<Integer> mList) {
+        this.mList = mList;
+    }
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_card_item, parent, false);
+        mCardAdapterHelper.onCreateViewHolder(parent, itemView);
+        return new ViewHolder(itemView);
+    }
+
+    @Override
+    public void onBindViewHolder(final ViewHolder holder, final int position) {
+        mCardAdapterHelper.onBindViewHolder(holder.itemView, position, getItemCount());
+        holder.mImageView.setImageResource(mList.get(position));
+        holder.mImageView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+               G.showToast( "" + position);
+            }
+        });
+    }
+
+    @Override
+    public int getItemCount() {
+        return mList.size();
+    }
+
+    public class ViewHolder extends RecyclerView.ViewHolder {
+        public final ImageView mImageView;
+
+        public ViewHolder(final View itemView) {
+            super(itemView);
+            mImageView = (ImageView) itemView.findViewById(R.id.imageView);
+        }
+
+    }
+
+}

+ 46 - 0
app/src/main/java/com/kfzs/duanduan/cardview/CardAdapterHelper.java

@@ -0,0 +1,46 @@
+package com.kfzs.duanduan.cardview;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+
+
+
+/**
+ * adapter中调用onCreateViewHolder, onBindViewHolder
+ * Created by jameson on 9/1/16.
+ */
+public class CardAdapterHelper {
+    private int mPagePadding = 15;
+    private int mShowLeftCardWidth = 15;
+
+    public void onCreateViewHolder(ViewGroup parent, View itemView) {
+        RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams();
+        lp.width = parent.getWidth() - ScreenUtil.dip2px(itemView.getContext(), 2 * (mPagePadding + mShowLeftCardWidth));
+        itemView.setLayoutParams(lp);
+    }
+
+    public void onBindViewHolder(View itemView, final int position, int itemCount) {
+        int padding = ScreenUtil.dip2px(itemView.getContext(), mPagePadding);
+        itemView.setPadding(padding, 0, padding, 0);
+        int leftMarin = position == 0 ? padding + ScreenUtil.dip2px(itemView.getContext(), mShowLeftCardWidth) : 0;
+        int rightMarin = position == itemCount - 1 ? padding + ScreenUtil.dip2px(itemView.getContext(), mShowLeftCardWidth) : 0;
+        setViewMargin(itemView, leftMarin, 0, rightMarin, 0);
+    }
+
+    private void setViewMargin(View view, int left, int top, int right, int bottom) {
+        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
+        if (lp.leftMargin != left || lp.topMargin != top || lp.rightMargin != right || lp.bottomMargin != bottom) {
+            lp.setMargins(left, top, right, bottom);
+            view.setLayoutParams(lp);
+        }
+    }
+
+    public void setPagePadding(int pagePadding) {
+        mPagePadding = pagePadding;
+    }
+
+    public void setShowLeftCardWidth(int showLeftCardWidth) {
+        mShowLeftCardWidth = showLeftCardWidth;
+    }
+}

+ 24 - 0
app/src/main/java/com/kfzs/duanduan/cardview/CardLinearSnapHelper.java

@@ -0,0 +1,24 @@
+package com.kfzs.duanduan.cardview;
+
+import android.support.annotation.NonNull;
+import android.support.v7.widget.LinearSnapHelper;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ * 防止卡片在第一页和最后一页因无法"居中"而一直循环调用onScrollStateChanged-->SnapHelper.snapToTargetExistingView-->onScrollStateChanged
+ * Created by jameson on 9/3/16.
+ */
+public class CardLinearSnapHelper extends LinearSnapHelper {
+    public boolean mNoNeedToScroll = false;
+
+    @Override
+    public int[] calculateDistanceToFinalSnap(@NonNull RecyclerView.LayoutManager layoutManager, @NonNull View targetView) {
+        if (mNoNeedToScroll) {
+            return new int[]{0, 0};
+        } else {
+            return super.calculateDistanceToFinalSnap(layoutManager, targetView);
+        }
+    }
+
+}

+ 150 - 0
app/src/main/java/com/kfzs/duanduan/cardview/CardScaleHelper.java

@@ -0,0 +1,150 @@
+package com.kfzs.duanduan.cardview;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+/**
+ * Created by jameson on 8/30/16.
+ */
+public class CardScaleHelper {
+    private RecyclerView mRecyclerView;
+    private Context mContext;
+
+    private float mScale = 0.9f; // 两边视图scale
+    private int mPagePadding = 15; // 卡片的padding, 卡片间的距离等于2倍的mPagePadding
+    private int mShowLeftCardWidth = 15;   // 左边卡片显示大小
+
+    private int mCardWidth; // 卡片宽度
+    private int mOnePageWidth; // 滑动一页的距离
+    private int mCardGalleryWidth;
+
+    private int mCurrentItemPos;
+    private int mCurrentItemOffset;
+
+    private CardLinearSnapHelper mLinearSnapHelper = new CardLinearSnapHelper();
+
+    public void attachToRecyclerView(final RecyclerView mRecyclerView) {
+        // 开启log会影响滑动体验, 调试时才开启
+        LogUtils.mLogEnable = false;
+        this.mRecyclerView = mRecyclerView;
+        mContext = mRecyclerView.getContext();
+        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+                super.onScrollStateChanged(recyclerView, newState);
+                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                    mLinearSnapHelper.mNoNeedToScroll = mCurrentItemOffset == 0 || mCurrentItemOffset == getDestItemOffset(mRecyclerView.getAdapter().getItemCount() - 1);
+                } else {
+                    mLinearSnapHelper.mNoNeedToScroll = false;
+                }
+            }
+
+            @Override
+            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+                super.onScrolled(recyclerView, dx, dy);
+                // dx>0则表示右滑, dx<0表示左滑, dy<0表示上滑, dy>0表示下滑
+                if(dx != 0){//去掉奇怪的内存疯涨问题
+                    mCurrentItemOffset += dx;
+                    computeCurrentItemPos();
+                    LogUtils.v(String.format("dx=%s, dy=%s, mScrolledX=%s", dx, dy, mCurrentItemOffset));
+                    onScrolledChangedCallback();
+                }
+            }
+        });
+
+        initWidth();
+        mLinearSnapHelper.attachToRecyclerView(mRecyclerView);
+    }
+
+    /**
+     * 初始化卡片宽度
+     */
+    private void initWidth() {
+        mRecyclerView.post(new Runnable() {
+            @Override
+            public void run() {
+                mCardGalleryWidth = mRecyclerView.getWidth();
+                mCardWidth = mCardGalleryWidth - ScreenUtil.dip2px(mContext, 2 * (mPagePadding + mShowLeftCardWidth));
+                mOnePageWidth = mCardWidth;
+                mRecyclerView.smoothScrollToPosition(mCurrentItemPos);
+                onScrolledChangedCallback();
+            }
+        });
+    }
+
+    public void setCurrentItemPos(int currentItemPos) {
+        this.mCurrentItemPos = currentItemPos;
+    }
+
+    public int getCurrentItemPos() {
+        return mCurrentItemPos;
+    }
+
+    private int getDestItemOffset(int destPos) {
+        return mOnePageWidth * destPos;
+    }
+
+    /**
+     * 计算mCurrentItemOffset
+     */
+    private void computeCurrentItemPos() {
+        if (mOnePageWidth <= 0) return;
+        boolean pageChanged = false;
+        // 滑动超过一页说明已翻页
+        if (Math.abs(mCurrentItemOffset - mCurrentItemPos * mOnePageWidth) >= mOnePageWidth) {
+            pageChanged = true;
+        }
+        if (pageChanged) {
+            int tempPos = mCurrentItemPos;
+
+            mCurrentItemPos = mCurrentItemOffset / mOnePageWidth;
+            LogUtils.d(String.format("=======onCurrentItemPos Changed======= tempPos=%s, mCurrentItemPos=%s", tempPos, mCurrentItemPos));
+        }
+    }
+
+    /**
+     * RecyclerView位移事件监听, view大小随位移事件变化
+     */
+    private void onScrolledChangedCallback() {
+        int offset = mCurrentItemOffset - mCurrentItemPos * mOnePageWidth;
+        float percent = (float) Math.max(Math.abs(offset) * 1.0 / mOnePageWidth, 0.0001);
+
+        LogUtils.d(String.format("offset=%s, percent=%s", offset, percent));
+        View leftView = null;
+        View currentView;
+        View rightView = null;
+        if (mCurrentItemPos > 0) {
+            leftView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos - 1);
+        }
+        currentView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos);
+        if (mCurrentItemPos < mRecyclerView.getAdapter().getItemCount() - 1) {
+            rightView = mRecyclerView.getLayoutManager().findViewByPosition(mCurrentItemPos + 1);
+        }
+
+        if (leftView != null) {
+            // y = (1 - mScale)x + mScale
+            leftView.setScaleY((1 - mScale) * percent + mScale);
+        }
+        if (currentView != null) {
+            // y = (mScale - 1)x + 1
+            currentView.setScaleY((mScale - 1) * percent + 1);
+        }
+        if (rightView != null) {
+            // y = (1 - mScale)x + mScale
+            rightView.setScaleY((1 - mScale) * percent + mScale);
+        }
+    }
+
+    public void setScale(float scale) {
+        mScale = scale;
+    }
+
+    public void setPagePadding(int pagePadding) {
+        mPagePadding = pagePadding;
+    }
+
+    public void setShowLeftCardWidth(int showLeftCardWidth) {
+        mShowLeftCardWidth = showLeftCardWidth;
+    }
+}

+ 147 - 0
app/src/main/java/com/kfzs/duanduan/cardview/LogUtils.java

@@ -0,0 +1,147 @@
+package com.kfzs.duanduan.cardview;
+
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+/**
+ * 很好用的Log打印类,自动输出方法和行数
+ * Created by jameson on 12/19/15.
+ */
+public class LogUtils {
+
+    public static boolean mLogEnable = true;
+    public static final String PREFIX = "LogUtils--";
+
+    private static String mClassname;
+    private static ArrayList<String> mMethods;
+
+    static {
+        mClassname = LogUtils.class.getName();
+        mMethods = new ArrayList<>();
+
+        Method[] ms = LogUtils.class.getDeclaredMethods();
+        for (Method m : ms) {
+            mMethods.add(m.getName());
+        }
+    }
+
+    public static void init(boolean logEnable) {
+        mLogEnable = logEnable;
+    }
+
+    public static void d(String tag, String msg) {
+        if (mLogEnable) {
+            Log.d(tag, getMsgWithLineNumber(msg));
+        }
+    }
+
+    public static void e(String tag, String msg) {
+        if (mLogEnable) {
+            Log.e(tag, getMsgWithLineNumber(msg));
+        }
+    }
+
+    public static void i(String tag, String msg) {
+        if (mLogEnable) {
+            Log.i(tag, getMsgWithLineNumber(msg));
+        }
+    }
+
+    public static void w(String tag, String msg) {
+        if (mLogEnable) {
+            Log.w(tag, getMsgWithLineNumber(msg));
+        }
+    }
+
+    public static void v(String tag, String msg) {
+        if (mLogEnable) {
+            Log.v(tag, getMsgWithLineNumber(msg));
+        }
+    }
+
+
+    public static void d(String msg) {
+        if (mLogEnable) {
+            String[] content = getMsgAndTagWithLineNumber(msg);
+            Log.d(content[0], content[1]);
+        }
+    }
+
+    public static void e(String msg) {
+        if (mLogEnable) {
+            String[] content = getMsgAndTagWithLineNumber(msg);
+            Log.e(content[0], content[1]);
+        }
+    }
+
+    public static void i(String msg) {
+        if (mLogEnable) {
+            String[] content = getMsgAndTagWithLineNumber(msg);
+            Log.i(content[0], content[1]);
+        }
+    }
+
+    public static void i() {
+        if (mLogEnable) {
+            String[] content = getMsgAndTagWithLineNumber("");
+            Log.i(content[0], content[1]);
+        }
+    }
+
+    public static void w(String msg) {
+        if (mLogEnable) {
+            String[] content = getMsgAndTagWithLineNumber(msg);
+            Log.w(content[0], content[1]);
+        }
+    }
+
+    public static void v(String msg) {
+        if (mLogEnable) {
+            String[] content = getMsgAndTagWithLineNumber(msg);
+            Log.v(content[0], content[1]);
+        }
+    }
+
+    public static String getMsgWithLineNumber(String msg) {
+        try {
+            for (StackTraceElement st : (new Throwable()).getStackTrace()) {
+                if (mClassname.equals(st.getClassName()) || mMethods.contains(st.getMethodName())) {
+                    continue;
+                } else {
+                    int b = st.getClassName().lastIndexOf(".") + 1;
+                    String message = new StringBuilder(st.getClassName().substring(b)).append("->").append(st.getMethodName())
+                            .append("():").append(st.getLineNumber()).append(msg).toString();
+                    return message;
+                }
+
+            }
+        } catch (Exception e) {
+
+        }
+        return msg;
+    }
+
+    public static String[] getMsgAndTagWithLineNumber(String msg) {
+        try {
+            for (StackTraceElement st : (new Throwable()).getStackTrace()) {
+                if (mClassname.equals(st.getClassName()) || mMethods.contains(st.getMethodName())) {
+                    continue;
+                } else {
+                    int b = st.getClassName().lastIndexOf(".") + 1;
+                    String TAG = PREFIX + st.getClassName().substring(b);
+                    String message = st.getMethodName() + "():" + st.getLineNumber() + "->" + msg;
+                    String[] content = new String[]{TAG, message};
+                    return content;
+                }
+
+            }
+        } catch (Exception e) {
+
+        }
+        return new String[]{"universal tag", msg};
+    }
+
+
+}

+ 38 - 0
app/src/main/java/com/kfzs/duanduan/cardview/ScreenUtil.java

@@ -0,0 +1,38 @@
+package com.kfzs.duanduan.cardview;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Point;
+import android.os.Build;
+import android.view.WindowManager;
+
+/**
+ * Created by jameson on 12/19/15.
+ */
+public class ScreenUtil {
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+    public static int getScreenWidth(Context context) {
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Point p = new Point();
+        wm.getDefaultDisplay().getSize(p);
+        return p.x;
+    }
+
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+    public static int getScreenHeight(Context context) {
+        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        Point p = new Point();
+        wm.getDefaultDisplay().getSize(p);
+        return p.y;
+    }
+
+    public static int dip2px(Context context, float dpValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dpValue * scale + 0.5f);
+    }
+
+    public static int px2dip(Context context, float pxValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (pxValue / scale + 0.5f);
+    }
+}

+ 44 - 0
app/src/main/java/com/kfzs/duanduan/cardview/SpeedRecyclerView.java

@@ -0,0 +1,44 @@
+package com.kfzs.duanduan.cardview;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+
+/**
+ * 控制fling速度的RecyclerView
+ *
+ * Created by jameson on 9/1/16.
+ */
+public class SpeedRecyclerView extends RecyclerView {
+    private static final float FLING_SCALE_DOWN_FACTOR = 0.5f; // 减速因子
+    private static final int FLING_MAX_VELOCITY = 8000; // 最大顺时滑动速度
+
+    public SpeedRecyclerView(Context context) {
+        super(context);
+    }
+
+    public SpeedRecyclerView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public SpeedRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    public boolean fling(int velocityX, int velocityY) {
+        velocityX = solveVelocity(velocityX);
+        velocityY = solveVelocity(velocityY);
+        return super.fling(velocityX, velocityY);
+    }
+
+    private int solveVelocity(int velocity) {
+        if (velocity > 0) {
+            return Math.min(velocity, FLING_MAX_VELOCITY);
+        } else {
+            return Math.max(velocity, -FLING_MAX_VELOCITY);
+        }
+    }
+
+}

+ 42 - 0
app/src/main/java/com/kfzs/duanduan/cardview/ViewSwitchUtils.java

@@ -0,0 +1,42 @@
+package com.kfzs.duanduan.cardview;
+
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.TransitionDrawable;
+import android.widget.ImageView;
+
+/**
+ * 图片背景切换动画帮助类
+ *
+ * Created by jameson on 9/3/16.
+ */
+public class ViewSwitchUtils {
+
+    public static void startSwitchBackgroundAnim(ImageView view, Bitmap bitmap) {
+        Drawable oldDrawable = view.getDrawable();
+        Drawable oldBitmapDrawable ;
+        TransitionDrawable oldTransitionDrawable = null;
+        if (oldDrawable instanceof TransitionDrawable) {
+            oldTransitionDrawable = (TransitionDrawable) oldDrawable;
+            oldBitmapDrawable = oldTransitionDrawable.findDrawableByLayerId(oldTransitionDrawable.getId(1));
+        } else if (oldDrawable instanceof BitmapDrawable) {
+            oldBitmapDrawable = oldDrawable;
+        } else {
+            oldBitmapDrawable = new ColorDrawable(0xffc2c2c2);
+        }
+
+        if (oldTransitionDrawable == null) {
+            oldTransitionDrawable = new TransitionDrawable(new Drawable[]{oldBitmapDrawable, new BitmapDrawable(bitmap)});
+            oldTransitionDrawable.setId(0, 0);
+            oldTransitionDrawable.setId(1, 1);
+            oldTransitionDrawable.setCrossFadeEnabled(true);
+            view.setImageDrawable(oldTransitionDrawable);
+        } else {
+            oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(0), oldBitmapDrawable);
+            oldTransitionDrawable.setDrawableByLayerId(oldTransitionDrawable.getId(1), new BitmapDrawable(bitmap));
+        }
+        oldTransitionDrawable.startTransition(1000);
+    }
+}

+ 87 - 0
app/src/main/java/com/kfzs/duanduan/cardview/ViewUtil.java

@@ -0,0 +1,87 @@
+package com.kfzs.duanduan.cardview;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.View;
+import android.widget.AbsListView;
+
+/**
+ * ViewUtil
+ * <p>
+ * Created by jameson on 12/19/15.
+ */
+public class ViewUtil {
+    /**
+     * 返回AbsListView scrollY
+     *
+     * @param view          view
+     * @param mHeaderHeight absListView header高度
+     * @return
+     */
+    public static int getScrollY(AbsListView view, int mHeaderHeight) {
+        if (view == null) return 0;
+
+        View c = view.getChildAt(0);
+        if (c == null) {
+            return 0;
+        }
+
+        int firstVisiblePosition = view.getFirstVisiblePosition();
+        int top = c.getTop();
+
+        int headerHeight = 0;
+        if (firstVisiblePosition >= view.getChildCount()) {
+            headerHeight = mHeaderHeight;
+        }
+
+        return -top + firstVisiblePosition * c.getHeight() + headerHeight;
+    }
+
+    /**
+     * 返回View的矩阵(减去statusBar高度)
+     *
+     * @param view view
+     * @return
+     */
+    public static Rect getOnScreenRect(View view) {
+        return getOnScreenRect(view, true);
+    }
+
+    /**
+     * 返回View的矩阵
+     *
+     * @param view            view
+     * @param removeStatusBar 是否包含算StatusBar高度
+     * @return
+     */
+    public static Rect getOnScreenRect(View view, boolean removeStatusBar) {
+        Rect rect = new Rect();
+        final int[] location = new int[2];
+        view.getLocationOnScreen(location);
+
+        int statusBarHeight = 0;
+        if (removeStatusBar) {
+            Rect windowRect = new Rect();
+            view.getWindowVisibleDisplayFrame(windowRect);
+            statusBarHeight = windowRect.top;
+        }
+
+        rect.set(location[0], location[1] - statusBarHeight, location[0] + view.getWidth(), location[1] - statusBarHeight + view.getHeight());
+        return rect;
+    }
+
+    /**
+     * 获取statusBar高度
+     *
+     * @param context context
+     * @return
+     */
+    public int getStatusBarHeight(Context context) {
+        int result = 0;
+        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
+        if (resourceId > 0) {
+            result = context.getResources().getDimensionPixelSize(resourceId);
+        }
+        return result;
+    }
+}

+ 20 - 0
app/src/main/java/com/kfzs/duanduan/fragment/FgtSmallSheep.java

@@ -3,6 +3,8 @@ package com.kfzs.duanduan.fragment;
 import android.annotation.SuppressLint;
 import android.app.ActionBar;
 import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.graphics.Color;
@@ -321,6 +323,24 @@ public class FgtSmallSheep extends BaseCompatFragment implements SmallSheepContr
                 }
             }
         });
+        edInvitationCode.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View view) {
+                // 获取系统剪贴板
+                ClipboardManager clipboard = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
+                // 获取剪贴板的剪贴数据集
+                ClipData clipData = clipboard.getPrimaryClip();
+
+                if (clipData != null && clipData.getItemCount() > 0) {
+                    // 从数据集中获取(粘贴)第一条文本数据
+                    CharSequence codetext = clipData.getItemAt(0).getText();
+                    if (!TextUtils.isEmpty(codetext)){
+                        edInvitationCode.setText(codetext);
+                    }
+                }
+                return false;
+            }
+        });
         ivClose.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {

+ 116 - 1
app/src/main/java/com/sheep/gamegroup/util/ViewUtil.java

@@ -4,10 +4,13 @@ import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
 import android.app.ProgressDialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -18,6 +21,7 @@ import android.provider.MediaStore;
 import android.support.v4.app.FragmentActivity;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.text.Html;
 import android.text.TextUtils;
@@ -45,6 +49,11 @@ import com.bumptech.glide.request.RequestOptions;
 import com.google.gson.Gson;
 import com.jcodecraeer.xrecyclerview.CustomFooterViewCallBack;
 import com.jcodecraeer.xrecyclerview.XRecyclerView;
+import com.kfzs.duanduan.cardview.BlurBitmapUtils;
+import com.kfzs.duanduan.cardview.CardAdapter;
+import com.kfzs.duanduan.cardview.CardScaleHelper;
+import com.kfzs.duanduan.cardview.SpeedRecyclerView;
+import com.kfzs.duanduan.cardview.ViewSwitchUtils;
 import com.kfzs.duanduan.fragment.FgtPersonalCenter;
 import com.sheep.gamegroup.dateview.DatePickerDialog;
 import com.sheep.gamegroup.dateview.DateUtil;
@@ -81,6 +90,7 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -104,6 +114,9 @@ public class ViewUtil {
     public static final int REQUEST_CODE_TASK_LIST = 110;
     private static ViewUtil viewUtil;
     static RobTask mRobTask;
+    private static int mLastPos = -1;
+    private static CardScaleHelper mCardScaleHelper = new CardScaleHelper();
+    private static Runnable mBlurRunnable;
 
     public static ViewUtil newInstance() {
         if (viewUtil == null) {
@@ -352,6 +365,24 @@ public class ViewUtil {
                 }
             }
         });
+        edInvitationCode.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
+            public boolean onLongClick(View view) {
+                // 获取系统剪贴板
+                ClipboardManager clipboard = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE);
+               // 获取剪贴板的剪贴数据集
+                ClipData clipData = clipboard.getPrimaryClip();
+
+                if (clipData != null && clipData.getItemCount() > 0) {
+                    // 从数据集中获取(粘贴)第一条文本数据
+                    CharSequence codetext = clipData.getItemAt(0).getText();
+                    if (!TextUtils.isEmpty(codetext)){
+                        edInvitationCode.setText(codetext);
+                    }
+                }
+                return false;
+            }
+        });
         ivClose.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
@@ -1307,6 +1338,79 @@ public class ViewUtil {
     }
 
     /**
+     * 初始化画廊
+     *
+     * @param mRecyclerView ,recycleView
+     * @param mBlurView     显示的ImageView
+     * @param mList         图片文件地址集合,
+     * @param context       。。。
+     */
+    private static void init(SpeedRecyclerView mRecyclerView, ImageView mBlurView, List<Integer> mList, Context context) {
+        if (mList == null) {
+            mList = new ArrayList<>();
+        }
+        for (int i = 0; i < 10; i++) {
+            mList.add(R.drawable.kaipin);
+            mList.add(R.drawable.kaipin);
+            mList.add(R.drawable.kaipin);
+        }
+
+        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
+        mRecyclerView.setLayoutManager(linearLayoutManager);
+        mRecyclerView.setAdapter(new CardAdapter(mList));
+        // mRecyclerView绑定scale效果
+        mCardScaleHelper.setCurrentItemPos(2);
+        mCardScaleHelper.attachToRecyclerView(mRecyclerView);
+
+        initBlurBackground(mBlurView, mRecyclerView, mList, context);
+    }
+
+    /**
+     * 给画廊设置背景
+     *
+     * @param mBlurView
+     * @param mRecyclerView
+     * @param mList
+     * @param context
+     */
+    private static void initBlurBackground(ImageView mBlurView, RecyclerView mRecyclerView, final List<Integer> mList, final Context context) {
+        final ImageView finalMBlurView = mBlurView;
+        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
+                super.onScrollStateChanged(recyclerView, newState);
+                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                    notifyBackgroundChange(finalMBlurView, mList, context);
+                }
+            }
+        });
+
+        notifyBackgroundChange(mBlurView, mList, context);
+    }
+
+    /**
+     * 检测画廊图片变化
+     *
+     * @param mBlurView
+     * @param mList
+     * @param context
+     */
+    private static void notifyBackgroundChange(final ImageView mBlurView, List<Integer> mList, final Context context) {
+        if (mLastPos == mCardScaleHelper.getCurrentItemPos()) return;
+        mLastPos = mCardScaleHelper.getCurrentItemPos();
+        final int resId = mList.get(mCardScaleHelper.getCurrentItemPos());
+        mBlurView.removeCallbacks(mBlurRunnable);
+        mBlurRunnable = new Runnable() {
+            @Override
+            public void run() {
+                Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
+                ViewSwitchUtils.startSwitchBackgroundAnim(mBlurView, BlurBitmapUtils.getBlurBitmap(mBlurView.getContext(), bitmap, 15));
+            }
+        };
+        mBlurView.postDelayed(mBlurRunnable, 500);
+    }
+
+    /**
      * 添加游戏账户
      */
     public void showAddAccount(Activity activity, Action1<Integer> action1) {
@@ -1316,7 +1420,7 @@ public class ViewUtil {
     public static void showShareDialog(final Activity activity, final String url, final String description) {
         View dialog_parent = View.inflate(activity, R.layout.ask_to_share, null);
         final AlertDialog dialog = new AlertDialog.Builder(activity, R.style.AppTheme_Dialog_Alert)
-                .setView(dialog_parent)
+                .setView(dialog_parent).setCancelable(true)
                 .create();
         Window windows = dialog.getWindow();
         windows.setGravity(Gravity.BOTTOM); //Dialog在屏幕底部弹出来
@@ -1324,6 +1428,11 @@ public class ViewUtil {
         layoutParams.width = 400; //设置Dialog的宽
         layoutParams.height = 200; //设置Dialog的高
         windows.setWindowAnimations(R.style.Rising);//设置动画效果
+        View viewEmpty = dialog_parent.findViewById(R.id.empty_view);
+       // SpeedRecyclerView speedRecyclerView = dialog_parent.findViewById(R.id.recyclerView);
+       // ImageView card = dialog_parent.findViewById(R.id.blurView);
+       // List<Integer> mList = new ArrayList<>();
+       // init(speedRecyclerView, card, mList, activity);
 //        TextView ask_share_title = dialog_parent.findViewById(R.id.ask_share_title);
         RecyclerView ask_share_list = dialog_parent.findViewById(R.id.ask_share_list);
         GridLayoutManager gridLayoutManager = new GridLayoutManager(activity, 5);
@@ -1348,6 +1457,12 @@ public class ViewUtil {
         nameList.add("QQ好友");
         nameList.add("朋友圈");
         nameList.add("复制链接");
+        viewEmpty.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                dialog.cancel();
+            }
+        });
         AdbCommonRecycler<String> adapter = new AdbCommonRecycler<String>(activity, list) {
 
             @Override

+ 42 - 10
app/src/main/res/layout/ask_to_share.xml

@@ -1,12 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="wrap_content">
 
     <RelativeLayout
+        android:id="@+id/layout_f"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom"
+        android:layout_alignParentBottom="true"
         android:background="#ffffffff">
 
         <TextView
@@ -17,7 +18,7 @@
             android:text="邀请好友"
             android:textColor="#ff333333"
             android:textSize="14sp" />
-<!--
+
         <TextView
             android:id="@+id/tv_copy"
             android:layout_width="40dp"
@@ -25,9 +26,10 @@
             android:layout_alignParentEnd="true"
             android:layout_marginEnd="15dp"
             android:layout_marginTop="20dp"
+            android:background="@drawable/shape_blue_stroke_withe_radius_5"
             android:gravity="center"
             android:text="复制"
-            android:background="@drawable/shape_blue_stroke_withe_radius_5"
+            android:visibility="gone"
             android:textColor="@color/white" />
 
         <TextView
@@ -37,9 +39,10 @@
             android:layout_marginRight="5dp"
             android:layout_marginTop="15dp"
             android:layout_toLeftOf="@id/tv_copy"
-            android:textColor="#ff333333"
             android:gravity="center"
-            android:text="12332" />
+            android:text="12332"
+            android:visibility="gone"
+            android:textColor="#ff333333" />
 
         <TextView
             android:id="@+id/tv_f_invatation"
@@ -49,8 +52,9 @@
             android:layout_marginTop="15dp"
             android:layout_toLeftOf="@id/tv_invitation_code"
             android:gravity="center"
-            android:textColor="#ff333333"
-            android:text="你的邀请码:" />-->
+            android:text="你的邀请码:"
+            android:visibility="gone"
+            android:textColor="#ff333333" />
 
 
         <android.support.v7.widget.RecyclerView
@@ -63,4 +67,32 @@
             android:layout_marginTop="20dp" />
     </RelativeLayout>
 
-</FrameLayout>
+   <RelativeLayout
+       android:layout_width="match_parent"
+       android:layout_height="450dp"
+       android:id="@+id/layout_f1"
+       android:layout_above="@id/layout_f"
+       android:visibility="gone">
+       <ImageView
+           android:id="@+id/blurView"
+           android:layout_width="match_parent"
+           android:layout_height="match_parent"
+           android:background="#3f000000"
+           android:scaleType="centerCrop"/>
+
+       <com.kfzs.duanduan.cardview.SpeedRecyclerView
+           android:id="@+id/recyclerView"
+           android:layout_width="match_parent"
+           android:layout_height="match_parent"
+           android:layout_marginBottom="30dp"
+           android:layout_marginTop="30dp"/>
+   </RelativeLayout>
+
+    <View
+        android:id="@+id/empty_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_above="@id/layout_f1"
+        android:visibility="gone"/>
+
+</RelativeLayout>

+ 2 - 0
app/src/main/res/layout/pop_get_redpackage.xml

@@ -28,6 +28,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal"
+            android:maxLength="10"
+            android:singleLine="true"
             android:layout_marginTop="20dp"
             android:background="@drawable/shape_get_redpackage_text_white"
             android:gravity="center"

+ 19 - 0
app/src/main/res/layout/view_card_item.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v7.widget.CardView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    app:cardCornerRadius="8dp"
+    app:cardElevation="6dp"
+    app:cardMaxElevation="12dp"
+    app:cardUseCompatPadding="true">
+
+    <ImageView
+        android:id="@+id/imageView"
+        android:layout_width="250dp"
+        android:layout_height="match_parent"
+        android:scaleType="centerCrop"
+        android:src="@drawable/kaipin"/>
+
+</android.support.v7.widget.CardView>