六邊形RecyclerView

weixin_34019929發表於2017-08-31

吐槽

來個效果圖吧先~


3113946-c98c8f9c25719150
這裡寫圖片描述

哎╮(╯▽╰)╭本月的開發專案終於在月底的時候拿到了介面,所以趕緊用迅雷掩耳不及盜鈴之響叮噹之勢擼完了那個從Eclipse中匯入的古董級專案.今天早上看到了個效果,感覺還挺有意思的,照著擼了一下,記錄總結一下實現過程吧

Github地址 https://github.com/fushuangdage/CustomView

簡介

其實也沒啥,這個動畫效果是RecyclerView 自帶的,之前一直用notifyDateSetChange(),一直沒有發現,其實recyclerview很好心的自帶了插入動畫,呼叫notifyItemInserted()插入即可
自己寫的也就兩個部分,第一自定義Drawable ,類似自定義view吧,將圖片化成六邊形.第二,通過自定義LayoutManager實現按照六邊形位置擺放1~7個子控制元件(原文是可以新增很多圈的,我就簡單寫寫了)

public class HiveDrawable extends Drawable {

    private Bitmap mBitmap;
    private Paint paint;
    private Path path;
    private Rect rect;


    public HiveDrawable(Bitmap bitmap) {
        init();
        if (bitmap!=null){
            BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
            paint.setShader(shader);
        }
    }

    @Override
    public int getIntrinsicHeight() {
        if (mBitmap!=null){
            return mBitmap.getHeight();
        }else {

            return super.getIntrinsicHeight();
        }
    }

    @Override
    public int getIntrinsicWidth() {
        if (mBitmap!=null){
            return mBitmap.getWidth();
        }else {
            return super.getIntrinsicWidth();
        }
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
        super.setBounds(left, top, right, bottom);
        rect = new Rect();
        rect.set(left,top,right,bottom);
        int l = rect.width() / 2;  //考慮橫向的情況
        int h = rect.height();
        double v = Math.sqrt(3) / 2;

        path.reset();
        path.moveTo(left,h/2);
        path.lineTo(left+l/2, (float) (h/2-v*l));
        path.lineTo(right-l/2, (float) (h/2-v*l));
        path.lineTo(right,h/2);
        path.lineTo(right-l/2, (float) (h/2+v*l));
        path.lineTo(left+l/2, (float) (h/2+v*l));
        path.moveTo(left,h/2);
        
        path.close();
    }

    private void init() {

        if (paint==null){
            paint = new Paint();
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.FILL);
            paint.setStrokeWidth(3f);
        }

        if (path==null){
            path = new Path();
        }

    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        canvas.drawPath(path,paint);
    }

    @Override
    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
            if (paint!=null){
                paint.setAlpha(alpha);
            }
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
        if (paint!=null)
            paint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
        return 0;
    }
}

自定義LayouManager

public class HiveLayoutManager extends RecyclerView.LayoutManager {

    private List<List<RectF>> positionList=new ArrayList();

    @Override
    public RecyclerView.LayoutParams generateDefaultLayoutParams() {
        return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    }


    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {

        detachAndScrapAttachedViews(recycler);

//        removeAllViews();
        int childCount = state.getItemCount();

        View first = recycler.getViewForPosition(0);
        measureChildWithMargins(first,0,0);
        int left = (getWidth() - getDecoratedMeasuredWidth(first)) / 2;
        int right=(getWidth() + getDecoratedMeasuredWidth(first)) / 2;
        int top=(getHeight()-getDecoratedMeasuredHeight(first))/2;
        int bottom=(getHeight()+getDecoratedMeasuredHeight(first))/2;
        //數學計算 每一層的最後一個都為  n*n*3+3*n+1

        addView(first);

        layoutDecoratedWithMargins(first,left,top,right,bottom);

        int num=childCount>7?7:childCount;
        int cX = getWidth() / 2;
        int cY = getHeight() / 2;

        for (int i = 1; i <num; i++) {
            View view = recycler.getViewForPosition(i);
            addView(view);
            measureChildWithMargins(view,0,0);
            int height = getDecoratedMeasuredHeight(view);
            int width = getDecoratedMeasuredWidth(view);
            double cos = Math.cos(Math.PI /3* (i - 1));
            double sin = Math.sin(Math.PI /3 *(i - 1));
            double viewCY = getHeight()/2-height * cos;
            double viewCX = getWidth()/ 2 - height * sin;

            layoutDecoratedWithMargins(view, ((int) (viewCX - width / 2)), ((int) (viewCY - height / 2))
                    ,((int) (viewCX + width / 2)), ((int) (viewCY + height / 2)));
        }
        
    }
}

相關文章