android不规则图形控件显示背景图片以及点击效果,多边形控件实例

我们在开发应用的过程中,经常会遇见美术突发奇想,给你来个狂拽酷炫效果的情况。下面我们就来说一下多边形控件,以及他的点击。

先上图


一、首先定义各种图形

1.菱形

public class DiamondView extends ImageView {
    private Context mContext;
    private int mWidth;
    private int mHeight;

    // 以上方角点所在的点位置为模式名
    public static final int TYPE_LEFT_TOP = 0;

    private int mMode;
    private int mColor;
    private String mText;
    // 四个点的顺序,从leftTop开始计算,顺时针数过去,依次四个点
    private int mPointOne[];
    private int mPointTwo[];
    private int mPointThree[];
    private int mPointFour[];

    private Path mPath;
    private Paint mPaint;

    private boolean isClicked = false; //是否被按下

    public DiamondView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mPath = new Path();
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mColor = Color.parseColor("#FFFFFF");
        mPaint.setColor(mColor);
    }

    public void setMode(int model) {
        mMode = model;
        postInvalidate();
    }

    public void setColor(int color) {
        mColor = color;
        postInvalidate();
    }

    public void setText(String text) {
        mText = text;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.clipPath(mPath, Region.Op.INTERSECT);
        super.onDraw(canvas);
        if(!isClicked) {
            mPaint.setColor(Color.argb(180, 0, 0, 0));
            canvas.drawPath(mPath, mPaint);
        }
        if(mText != null) {
            mPaint.setFakeBoldText(true);
            mPaint.setTextSize(sp2px(mContext,13));
            mPaint.setColor(mColor);
            float tw = mPaint.measureText(mText);
            float th = mPaint.measureText(mText)/mText.length();
            switch (mMode) {
                case TYPE_LEFT_TOP:
                    canvas.drawText(mText, (mWidth - tw)/2f, (mHeight+th)/2f, mPaint);
                    break;
            }
        }
    }

    @Override
    protected void onSizeChanged(int width, int height, int oldw, int oldh) {
        super.onSizeChanged(width, height, oldw, oldh);
        mWidth = width;
        mHeight = height;
        switch (mMode) {
            case TYPE_LEFT_TOP:
                mPointOne = new int[] { 0, 0 };
                mPointTwo = new int[] { width*140/250, 0 };
                mPointThree = new int[] { width, height };
                mPointFour = new int[] { width*110/250, height };
                break;
        }

        if (null != mPointOne) {
            mPath.moveTo(mPointOne[0], mPointOne[1]);
            mPath.lineTo(mPointTwo[0], mPointTwo[1]);
            mPath.lineTo(mPointThree[0], mPointThree[1]);
            mPath.lineTo(mPointFour[0], mPointFour[1]);
            mPath.close();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        RectF bounds = new RectF();
        mPath.computeBounds(bounds, true);
        Region region = new Region();
        region.setPath(mPath, new Region((int)bounds.left, (int)bounds.top,(int)bounds.right, (int)bounds.bottom));
        boolean ct =  region.contains((int)event.getX(), (int)event.getY());

        if(event.getAction() == MotionEvent.ACTION_DOWN){
            if(ct){
                isClicked = true;
                invalidate();
                return true;
            }
            return false;
        }else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){
            if(isClicked){
                isClicked = false;
                invalidate();
                if (null != mOnClickListener && ct && event.getAction() != MotionEvent.ACTION_CANCEL) {
                    mOnClickListener.onClick(this);
                    return true;
                }
            }
            return false;
        }else if(event.getAction() == MotionEvent.ACTION_MOVE){
            return isClicked;
        }
        return super.onTouchEvent(event);
    }

    private OnClickListener mOnClickListener;
    public void setOnViewClickListener(OnClickListener clickListener){
        mOnClickListener = clickListener;
    }

    //计算两点的距离
    private int distance(PointF point1, PointF point2) {
        int disX = (int) Math.abs(point1.x - point2.x);
        int disY = (int) Math.abs(point1.y - point2.y);
        return (int) Math.sqrt(Math.pow(disX, 2) + Math.pow(disY, 2));
    }

    //将sp值转换为px值,保证文字大小不变
    public static int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

}

绘制图形主要依靠Path来定义四个点,围成一个菱形。在ondraw的时候再调用

canvas.clipPath(mPath, Region.Op.INTERSECT);来切割画布,使得图片显示范围也在菱形内。
点击的时候靠的是Region 和path配合使用,判断点击的点是否在path勾勒的范围内,从而控制触摸事件。
 
 
 
 
除了菱形以外,还有其他的形状的类,代码太多不一一列举,文章结尾会附带完整项目包。
 
 
各种形状定义好之后就是排布
 
 
先写在xml布局文件中
 
 
<com.example.lupingshenqi.QiQiaoLayout android:id="@+id/activity_main_qiqiaolayout"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:padding="10dp">
    <com.example.lupingshenqi.TriangleView
        android:id="@+id/classify_1"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.TriangleView
        android:id="@+id/classify_2"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.TriangleView
        android:id="@+id/classify_3"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.DiamondView
        android:id="@+id/classify_4"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.TriangleView
        android:id="@+id/classify_5"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.SquareView
        android:id="@+id/classify_6"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.TriangleView
        android:id="@+id/classify_7"
        android:layout_width="100dp"
        android:layout_height="100dp" />
    <com.example.lupingshenqi.TriangleView
        android:id="@+id/classify_8"
        android:layout_width="100dp"
        android:layout_height="100dp" />
</com.example.lupingshenqi.QiQiaoLayout>

然后是在onSizeChanged的时候进行重新排布
 
 
 
 
public class QiQiaoLayout extends RelativeLayout{
    private ArrayList<CategoryBean> mClassifyList  = new ArrayList<>();
    public QiQiaoLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public  void setDate(ArrayList<CategoryBean> list){
        mClassifyList.clear();
        if(list!=null){
            mClassifyList.addAll(list);
        }
        if(mClassifyList!=null){
            for (int i=0;i<mClassifyList.size() && i<getChildCount();i++) {
                CategoryBean bean = mClassifyList.get(i);
                if(getChildAt(i) instanceof TriangleView){
                    TriangleView view = (TriangleView)getChildAt(i);
                    GlideImageLoadUtils.displayImage(getContext(), bean.categoryIconUrl, view, GlideImageLoadUtils.getIconNormalOptions());
                    view.setText(bean.categoryName);
                    view.setOnViewClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Toast.makeText(getContext(),"点击了按钮!",Toast.LENGTH_SHORT).show();
                        }
                    });
                }else if(getChildAt(i) instanceof DiamondView) {
                    DiamondView view = (DiamondView)getChildAt(i);
                    GlideImageLoadUtils.displayImage(getContext(), bean.categoryIconUrl, view, GlideImageLoadUtils.getIconNormalOptions());
                    view.setText(bean.categoryName);
                    view.setOnViewClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Toast.makeText(getContext(),"点击了按钮!",Toast.LENGTH_SHORT).show();
                        }
                    });
                }else if(getChildAt(i) instanceof SquareView) {
                    SquareView view = (SquareView)getChildAt(i);
                    GlideImageLoadUtils.displayImage(getContext(), bean.categoryIconUrl, view, GlideImageLoadUtils.getIconNormalOptions());
                    view.setText(bean.categoryName);
                    view.setOnViewClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            Toast.makeText(getContext(),"点击了按钮!",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }
        postInvalidate();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        TriangleView mClassifyView1 = (TriangleView) findViewById(R.id.classify_1);
        mClassifyView1.setMode(TriangleView.TYPE_LEFT_TOP);

        TriangleView mClassifyView2 = (TriangleView) findViewById(R.id.classify_2);
        mClassifyView2.setMode(TriangleView.TYPE_RIGHT_BOTTOM);

        TriangleView mClassifyView3 = (TriangleView) findViewById(R.id.classify_3);
        mClassifyView3.setMode(TriangleView.TYPE_RIGHT_MIDDLE);

        DiamondView mClassifyView4 = (DiamondView) findViewById(R.id.classify_4);
        mClassifyView4.setMode(DiamondView.TYPE_LEFT_TOP);

        TriangleView mClassifyView5 = (TriangleView) findViewById(R.id.classify_5);
        mClassifyView5.setMode(TriangleView.TYPE_RIGHT_BOTTOM_SMAILL);

        SquareView mClassifyView6 = (SquareView) findViewById(R.id.classify_6);

        TriangleView mClassifyView7 = (TriangleView) findViewById(R.id.classify_7);
        mClassifyView7.setMode(TriangleView.TYPE_LEFT_BOTTOM);

        TriangleView mClassifyView8 = (TriangleView) findViewById(R.id.classify_8);
        mClassifyView8.setMode(TriangleView.TYPE_RIGHT_TOP);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        w = w - getPaddingRight() - getPaddingLeft();
        float scale = w/660f;

        QiQiaoLayout.LayoutParams params = new QiQiaoLayout.LayoutParams((int)(230*scale),(int)(230*scale));
        params.setMargins(0,0,(int)(10*scale),(int)(10*scale));
        getChildAt(0).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(230*scale),(int)(230*scale));
        params.setMargins((int)(10*scale),(int)(10*scale),0,0);
        getChildAt(1).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(120*scale),(int)(240*scale));
        params.setMargins((int)(253*scale),0,0,0);
        getChildAt(2).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(250*scale),(int)(110*scale));
        params.setMargins((int)(270*scale),0,0,(int)(10*scale));
        getChildAt(3).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(120*scale),(int)(120*scale));
        params.setMargins((int)(270*scale),(int)(120*scale),0,0);
        getChildAt(4).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(120*scale),(int)(120*scale));
        params.setMargins((int)(400*scale),(int)(120*scale),0,0);
        getChildAt(5).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(120*scale),(int)(120*scale));
        params.setMargins((int)(530*scale),(int)(120*scale),0,0);
        getChildAt(6).setLayoutParams(params);

        params = new QiQiaoLayout.LayoutParams((int)(230*scale),(int)(230*scale));
        params.setMargins((int)(430*scale),0,0,0);
        getChildAt(7).setLayoutParams(params);


    }
 
 
 
 
话不多说,看整个项目的代码更容易明白,项目地址是
https://pan.baidu.com/s/1bFvakI

 
 
 
 
   
 

发布了63 篇原创文章 · 获赞 41 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/MarketAndTechnology/article/details/77868613