From ea8c1f044392c6e93f672488d9a7b8a7c54848da Mon Sep 17 00:00:00 2001 From: SL Date: Wed, 11 Dec 2024 15:07:31 +0800 Subject: [PATCH] fix:add Add method for adding a single channel member --- app/build.gradle | 1 - .../xinbida/wukongdemo/view/ChatLayout.java | 13 ++ .../xinbida/wukongdemo/view/ChatShape.java | 183 ++++++++++++++++++ .../com/xinbida/wukongdemo/view/ChatView.java | 137 +++++++++++++ app/src/main/res/layout/recv_order_layout.xml | 4 +- app/src/main/res/layout/recv_text_layout.xml | 4 +- app/src/main/res/layout/send_order_layout.xml | 4 +- app/src/main/res/layout/send_text_layout.xml | 4 +- app/src/main/res/values/chat.xml | 17 ++ 9 files changed, 358 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/xinbida/wukongdemo/view/ChatLayout.java create mode 100644 app/src/main/java/com/xinbida/wukongdemo/view/ChatShape.java create mode 100644 app/src/main/java/com/xinbida/wukongdemo/view/ChatView.java create mode 100644 app/src/main/res/values/chat.xml diff --git a/app/build.gradle b/app/build.gradle index eb3e668..7627a33 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,7 +40,6 @@ dependencies { implementation 'org.jetbrains:annotations:23.0.0' implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.7' implementation 'com.github.li-xiaojun:XPopup:2.9.19' - implementation 'com.github.bigdongdong:ChatView:2.0' //添加依赖 implementation('com.github.bumptech.glide:glide:4.16.0') { transitive = true } diff --git a/app/src/main/java/com/xinbida/wukongdemo/view/ChatLayout.java b/app/src/main/java/com/xinbida/wukongdemo/view/ChatLayout.java new file mode 100644 index 0000000..27d0164 --- /dev/null +++ b/app/src/main/java/com/xinbida/wukongdemo/view/ChatLayout.java @@ -0,0 +1,13 @@ +package com.xinbida.wukongdemo.view; + +import android.content.Context; +import android.graphics.Color; +import android.util.AttributeSet; +import android.widget.RelativeLayout; +public class ChatLayout extends RelativeLayout { + public ChatLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + this.setBackgroundColor(Color.parseColor("#00000000")); + } +} diff --git a/app/src/main/java/com/xinbida/wukongdemo/view/ChatShape.java b/app/src/main/java/com/xinbida/wukongdemo/view/ChatShape.java new file mode 100644 index 0000000..1e8b71d --- /dev/null +++ b/app/src/main/java/com/xinbida/wukongdemo/view/ChatShape.java @@ -0,0 +1,183 @@ +package com.xinbida.wukongdemo.view; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.shapes.Shape; + +class ChatShape extends Shape { + /** + * 箭头所在的方位(相对于view中心点而言) + */ + private String arrowDirection; + + /** + * 箭头是否在中间 + */ + private boolean isArrowCenter ; + + /** + * 箭头的宽度 (px) + */ + private int arrowWidth ; + + /** + * 箭头的高度 (px) + */ + private int arrowHeight; + + /** + * 气泡view是否有描边 + */ + private boolean hasStroke; + + /** + * 气泡描边的线的宽度 (px) + */ + private int strokeWidth ; + + /** + * 箭头距离view顶部的距离(px) + */ + private int arrowUpDistance ; + + /** + * view的圆角半径 (px) + */ + private int connerRadius ; + + /** + * 描边颜色 + */ + private int strokeColor ; + + /** + * 内填充颜色 + */ + private int fillColor ; + + + /*以下是默认设置,修正值为3F*/ + final float reviseValue = 3F; //向内修正值 + final float widthStart = reviseValue; + final float heightStart = reviseValue; + + /*以下是绘制时需要使用的变量*/ + + float width,height; //测量得到的view的长宽 + float widthEnd ; //减去修正值后,view右侧边界的坐标 + float heightEnd ; //减去修正值后,view底部边界的坐标 + + Path strokePath = new Path(); //边框path + Path fillPath = new Path(); //填充path + + /*全部设置的constructor*/ + public ChatShape(int arrowWidth, int arrowHeight, boolean isArrowCenter, + int strokeWidth, String arrowDirection, int arrowUpDistance, + int connerRadius, int strokeColor, int fillColor) { + this.arrowWidth = arrowWidth; + this.arrowHeight = arrowHeight; + this.isArrowCenter = isArrowCenter; + this.strokeWidth = strokeWidth; + this.arrowDirection = arrowDirection; + this.arrowUpDistance = arrowUpDistance; + this.connerRadius = connerRadius; + this.strokeColor = strokeColor; + this.fillColor = fillColor; + } + private void resizePath(float width, float height, Path path){ + widthEnd = width - widthStart; + heightEnd = height - widthStart; + if(isArrowCenter){ + arrowUpDistance = (int) (height/2-arrowHeight/2);//箭头居中设置 + } + + /*圆角的rect*/ + RectF connerRect = new RectF(); + + path.reset(); + /*绘制箭头*/ + path.moveTo(widthStart+arrowWidth, arrowUpDistance+arrowHeight); + path.lineTo(widthStart, arrowUpDistance+arrowHeight/2); + path.lineTo(widthStart+arrowWidth, arrowUpDistance); + /*绘制左上方直线*/ + path.lineTo(widthStart+arrowWidth, connerRadius); + /*绘制左上方圆角*/ + connerRect.set(widthStart+arrowWidth,heightStart,widthStart+arrowWidth+connerRadius,connerRadius); + path.arcTo(connerRect, 180,90); + /*上方直线边框*/ + path.lineTo(width-connerRadius, heightStart); + /*右上方圆角*/ + connerRect.set(width-connerRadius,heightStart,width,connerRadius); + path.arcTo(connerRect, 270,90); + /*右侧直线*/ + path.lineTo(width, height-connerRadius); + /*右下方圆角*/ + connerRect.set(width-connerRadius,height-connerRadius,width,height); + path.arcTo(connerRect, heightStart,90); + /*下方直线*/ + path.lineTo(widthStart+arrowWidth+connerRadius, height); + /*左下角圆角*/ + connerRect.set(widthStart+arrowWidth,height-connerRadius,widthStart+arrowWidth+connerRadius,height); + path.arcTo(connerRect, 90,90); + /*闭合路径*/ + path.close(); + + } + + @Override + protected void onResize(float width, float height) { + super.onResize(width, height); + this.width = width; + this.height = height; + /*测量外部的path + * 以及内部填充颜色*/ + resizePath(width-3, height-3 ,strokePath); + resizePath(width-3, height-3 ,fillPath); + + } + + @Override + public void draw(Canvas canvas, Paint paint) { + /*记录画布*/ + canvas.save(); + + /*如果箭头向右,则将画布翻转*/ + if(arrowDirection.equals("right")){ + /*以中间点进行画布翻转*/ + canvas.scale(-1,1,width/2,height/2); + } + /*先绘制填充 然后绘制边框 否则边框会被遮盖*/ + + /*绘制填充*/ + drawFill(canvas, paint); + /*绘制边框*/ + drawStroke(canvas, paint); + /*还原画布*/ + canvas.restore(); + } + + + + /*边框的paint*/ + private void drawStroke(Canvas canvas, Paint paint) { + paint.setColor(strokeColor); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeCap(Paint.Cap.ROUND); + paint.setStrokeJoin(Paint.Join.ROUND); + paint.setStrokeWidth(strokeWidth); + + canvas.drawPath(strokePath, paint); + } + /*填充的paint*/ + private void drawFill(Canvas canvas, Paint paint) { + paint.setColor(fillColor); + paint.setStyle(Paint.Style.FILL); + paint.setAntiAlias(true);//抗锯齿 + paint.setDither(true);//抖动 + paint.setStrokeWidth(strokeWidth); + + canvas.drawPath(fillPath, paint); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xinbida/wukongdemo/view/ChatView.java b/app/src/main/java/com/xinbida/wukongdemo/view/ChatView.java new file mode 100644 index 0000000..9fa3951 --- /dev/null +++ b/app/src/main/java/com/xinbida/wukongdemo/view/ChatView.java @@ -0,0 +1,137 @@ +package com.xinbida.wukongdemo.view; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.StateListDrawable; +import android.util.AttributeSet; + +import com.xinbida.wukongdemo.R; + +@SuppressLint("AppCompatCustomView") +public class ChatView extends ChatLayout { + /** + * 箭头所在的方位(相对于view中心点而言) + */ + private String arrowDirection = "left"; + + /** + * 箭头是否在中间 + */ + private boolean isArrowCenter = false ; + + /** + * 箭头的宽度 (px) + */ + private int arrowWidth = 15; + + /** + * 箭头的高度 (px) + */ + private int arrowHeight = 30; + + /** + * 气泡view是否有描边 + */ + private boolean hasStroke = false ; + + /** + * 气泡描边的线的宽度 (px) + */ + private int strokeWidth = 3 ; + + /** + * 箭头距离view顶部的距离(px) + */ + private int arrowUpDistance = 50; + + /** + * view的圆角半径 (px) + */ + private int connerRadius = 40; + + /** + * nomal描边颜色,默认边框灰色 + */ + private int strokeColor = Color.parseColor("#CCCCCC"); + + /** + * nomal内填充颜色,默认填充是淡蓝色 + */ + private int fillColor = Color.parseColor("#66CCFF"); + + /** + * press时view的内填充颜色,默认与nomal同色 + */ + private int pressStrokeColor = strokeColor; + + /** + * press时view内填充颜色,默认灰色 + */ + private int pressFillColor = strokeColor; + + + + + public ChatView(Context context, AttributeSet attrs) { + super(context, attrs); + + /*在这里关联自定义属性*/ + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.chat); + isArrowCenter = typedArray.getBoolean(R.styleable.chat_is_arrow_center,false); + hasStroke = typedArray.getBoolean(R.styleable.chat_has_stroke,false); + strokeWidth = typedArray.getDimensionPixelSize(R.styleable.chat_stroke_width,3); + arrowDirection = typedArray.getString(R.styleable.chat_arrow_direction); + arrowUpDistance = typedArray.getDimensionPixelSize(R.styleable.chat_arrow_up_distance,50); + connerRadius = typedArray.getDimensionPixelSize(R.styleable.chat_conner_radius,40); + strokeColor = typedArray.getColor(R.styleable.chat_stroke_color,strokeColor); + fillColor = typedArray.getColor(R.styleable.chat_fill_color,fillColor); + pressStrokeColor = typedArray.getColor(R.styleable.chat_press_stroke_color,pressStrokeColor); + pressFillColor = typedArray.getColor(R.styleable.chat_press_fill_color,pressFillColor); + + arrowWidth = typedArray.getDimensionPixelSize(R.styleable.chat_arrow_width,15); + arrowHeight = typedArray.getDimensionPixelSize(R.styleable.chat_arrow_height,30); + + + /** + * 在这里绘制背景,在onDraw()中绘制会造成UI堵塞卡顿 + */ + + this.setBackground(getSelectorBackground()); + } + + + private StateListDrawable stalistDrawable ; + private ChatShape chatShape; + + /*设置点击特效*/ + public StateListDrawable getSelectorBackground(){ + //初始化一个空对象 + if(stalistDrawable==null){ + stalistDrawable = new StateListDrawable(); + } + + /** + * 两种背景顺序不要反了,普通的在最后 + */ + + /*按压时显示的背景*/ + chatShape = new ChatShape(arrowWidth,arrowHeight,isArrowCenter,strokeWidth, + arrowDirection,arrowUpDistance,connerRadius,pressStrokeColor,pressFillColor); + stalistDrawable.addState(new int []{android.R.attr.state_pressed}, new ShapeDrawable(chatShape)); + + /*没有任何状态时显示的背景*/ + chatShape = new ChatShape(arrowWidth,arrowHeight,isArrowCenter,strokeWidth, + arrowDirection,arrowUpDistance,connerRadius,strokeColor,fillColor); + stalistDrawable.addState(new int []{}, new ShapeDrawable(chatShape)); + + return stalistDrawable; + } + + +} + + + diff --git a/app/src/main/res/layout/recv_order_layout.xml b/app/src/main/res/layout/recv_order_layout.xml index aada1e1..238624a 100644 --- a/app/src/main/res/layout/recv_order_layout.xml +++ b/app/src/main/res/layout/recv_order_layout.xml @@ -16,7 +16,7 @@ android:scaleType="centerCrop" android:src="@color/purple_200" /> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/recv_text_layout.xml b/app/src/main/res/layout/recv_text_layout.xml index 9722f94..9c18326 100644 --- a/app/src/main/res/layout/recv_text_layout.xml +++ b/app/src/main/res/layout/recv_text_layout.xml @@ -16,7 +16,7 @@ android:scaleType="centerCrop" android:src="@color/purple_200" /> - - + \ No newline at end of file diff --git a/app/src/main/res/layout/send_order_layout.xml b/app/src/main/res/layout/send_order_layout.xml index 99fe76f..b4b3d04 100644 --- a/app/src/main/res/layout/send_order_layout.xml +++ b/app/src/main/res/layout/send_order_layout.xml @@ -10,7 +10,7 @@ android:paddingTop="5dp" android:paddingBottom="5dp"> - - + - - + + + + + + + + + + + + + + + + + \ No newline at end of file