您的位置:首页 > 移动开发 > Android开发

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

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

先上图



一、首先定义各种图形

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





 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息