The Android custom layout realizes the Bubble window, which can control the angle direction and the offset of the bubble.
Effect chart
Realize
First customize a bubble layout.
/** * Bubble Layout/public class Bubblerelativelayout extends Relativelayout {/** * bubble angle direction/public enum Bubblelegor
ientation {top, left, right, BOTTOM, NONE} public static int PADDING = 30;
public static int leg_half_base = 30;
public static float stroke_width = 2.0f;
public static float Corner_radius = 8.0f;
public static int shadow_color = COLOR.ARGB (100, 0, 0, 0);
public static Float min_leg_distance = PADDING + leg_half_base;
Private Paint mfillpaint = null;
Private final Path MPath = new Path ();
Private final Path Mbubblelegprototype = new Path ();
Private final Paint mpaint = new Paint (Paint.dither_flag);
private float mbubblelegoffset = 0.75f;
Private Bubblelegorientation mbubbleorientation = Bubblelegorientation.left;
Public Bubblerelativelayout {This (context, NULL);
Public Bubblerelativelayout (context, AttributeSet attrs) {This (context, attrs, 0); Public Bubblerelativelayout, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle);
Init (context, attrs);
} private void Init (final context, final AttributeSet attrs) {//setgravity (gravity.center); Viewgroup.layoutparams params = new Viewgroup.layoutparams (ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
Setlayoutparams (params);
if (attrs!= null) {TypedArray a = Context.obtainstyledattributes (Attrs, r.styleable.bubble);
try {PADDING = a.getdimensionpixelsize (r.styleable.bubble_padding, PADDING);
Shadow_color = A.getint (R.styleable.bubble_shadowcolor, Shadow_color);
Leg_half_base = A.getdimensionpixelsize (R.styleable.bubble_halfbaseofleg, leg_half_base);
Min_leg_distance = PADDING + leg_half_base;
Stroke_width = A.getfloat (R.styleable.bubble_strokewidth, stroke_width);
Corner_radius = A.getfloat (R.styleable.bubble_cornerradius, Corner_radius);
Finally {if (a!= null) {a.recycle (); }} mpaint.setcolor (SHAdow_color);
Mpaint.setstyle (Style.fill);
Mpaint.setstrokecap (Cap.butt);
Mpaint.setantialias (TRUE);
Mpaint.setstrokewidth (Stroke_width);
Mpaint.setstrokejoin (Paint.Join.MITER);
Mpaint.setpatheffect (New Cornerpatheffect (Corner_radius));
if (Build.VERSION.SDK_INT >=) {setlayertype (Layer_type_software, mpaint);
} mfillpaint = new Paint (mpaint);
Mfillpaint.setcolor (Color.White);
Mfillpaint.setshader (New LinearGradient (100f, 0f, 100f, 200f, Color.White, Color.White, Tilemode.clamp));
if (Build.VERSION.SDK_INT >=) {setlayertype (Layer_type_software, mfillpaint);
} mpaint.setshadowlayer (2f, 2F, 5F, Shadow_color);
Renderbubblelegprototype ();
Setpadding (PADDING, PADDING, PADDING, PADDING);
} @Override protected void onconfigurationchanged (Configuration newconfig) {super.onconfigurationchanged (newconfig);
/** * Sharp point path/private void Renderbubblelegprototype () {mbubblelegprototype.moveto (0, 0); Mbubblelegprototype.linETo (PADDING * 1.5f,-padding/1.5f);
Mbubblelegprototype.lineto (PADDING * 1.5f, padding/1.5f);
Mbubblelegprototype.close (); } public void Setbubbleparams (final bubblelegorientation bubbleorientation, final float bubbleoffset) {mbubblelegoffs
ET = Bubbleoffset;
Mbubbleorientation = bubbleorientation; /** * According to the display direction, get the sharp angle position Matrix * @param width * @param height * @return/private matrix Renderbubblelegmatrix (FINA
L float width, final float height) {final float offset = Math.max (Mbubblelegoffset, min_leg_distance);
float DSTX = 0;
float dsty = math.min (offset, height-min_leg_distance);
Final Matrix matrix = new Matrix ();
Switch (mbubbleorientation) {Case TOP:DSTX = math.min (offset, width-min_leg_distance);
dsty = 0;
Matrix.postrotate (90);
Break
Case right:dstx = width;
Dsty = Math.min (offset, height-min_leg_distance);
Matrix.postrotate (180);
Break Case BOTTOM:DSTX = math.min (offset, Width-miN_leg_distance);
Dsty = height;
Matrix.postrotate (270);
Break
} matrix.posttranslate (Dstx, dsty);
return matrix;
} @Override protected void OnDraw (Canvas Canvas) {final float width = canvas.getwidth ();
Final float height = canvas.getheight ();
Mpath.rewind (); Mpath.addroundrect (New RECTF (PADDING, PADDING, width-padding, height-padding), Corner_radius, Corner_radius, Directio
N.CW);
Mpath.addpath (Mbubblelegprototype, Renderbubblelegmatrix (width, height));
Canvas.drawpath (MPath, mpaint);
Canvas.scale (width-stroke_width)/width, (height-stroke_width)/height, width/2f, height/2f);
Canvas.drawpath (MPath, mfillpaint);
}
}
Style Attrs.xml
<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
<declare-styleable name= "bubble" >
<attr name= "shadowcolor" format= "color"/> <attr name=
"padding" format= "Dimension"/>
< attr name= "strokewidth" format= "float"/> <attr name=
"Cornerradius" format= "float"/>
<attr "Halfbaseofleg" format= "Dimension"/>
</declare-styleable>
</resources>
Then customize a popupwindow to display the bubbles.
public class Bubblepopupwindow extends Popupwindow {private bubblerelativelayout bubbleview;
private context;
Public Bubblepopupwindow {this.context = context;
SetWidth (ViewGroup.LayoutParams.WRAP_CONTENT);
SetHeight (ViewGroup.LayoutParams.WRAP_CONTENT);
Setfocusable (TRUE);
Setoutsidetouchable (FALSE);
Setclippingenabled (FALSE);
Colordrawable DW = new colordrawable (0);
Setbackgrounddrawable (DW);
public void Setbubbleview (view view) {Bubbleview = new bubblerelativelayout (context);
Bubbleview.setbackgroundcolor (color.transparent);
Bubbleview.addview (view);
Setcontentview (Bubbleview);
public void SetParam (int width, int height) {setwidth (width);
SetHeight (height);
public void Show (View parent) {Show (parent, Gravity.top, Getmeasuredwidth ()/2);
public void Show (View parent, int gravity) {Show (parent, Gravity, Getmeasuredwidth ()/2); /** * Show Window * * @param parent * @param gravity * @parAm Bubbleoffset The bubble tip angle position offset. Default is in center/public void Show (View parent, int gravity, float bubbleoffset) {bubblerelativelayout.bubblelegorientation
orientation = BubbleRelativeLayout.BubbleLegOrientation.LEFT; if (!this.isshowing ()) {switch (Gravity) {Case Gravity.BOTTOM:orientation = Bubblerelativelayout.bubblelego Rientation.
Top;
Break
Case Gravity.TOP:orientation = BubbleRelativeLayout.BubbleLegOrientation.BOTTOM;
Break
Case Gravity.RIGHT:orientation = BubbleRelativeLayout.BubbleLegOrientation.LEFT;
Break
Case Gravity.LEFT:orientation = BubbleRelativeLayout.BubbleLegOrientation.RIGHT;
Break
Default:break; } bubbleview.setbubbleparams (orientation, bubbleoffset);
Set the bubble layout direction and sharp angle offset int[] location = new INT[2];
Parent.getlocationonscreen (location);
Switch (Gravity) {case Gravity.BOTTOM:showAsDropDown (parent);
Break Case Gravity.TOP:showAtLocation (Parent, Gravity.no_Gravity, location[0], location[1]-getmeasureheight ());
Break Case Gravity.RIGHT:showAtLocation (parent, gravity.no_gravity, Location[0] + parent.getwidth (), Location[1]-(parent
. GetHeight ()/2));
Break Case Gravity.LEFT:showAtLocation (parent, gravity.no_gravity, Location[0]-getmeasuredwidth (), Location[1]-(parent
. GetHeight ()/2));
Break
Default:break;
} else {This.dismiss (); }/** * Measuring height * * @return/public int getmeasureheight () {Getcontentview (). Measure (View.MeasureSpec.UNS
Pecified, View.MeasureSpec.UNSPECIFIED);
int popheight = Getcontentview (). Getmeasuredheight ();
return popheight; /** * Measuring Width * * @return/public int getmeasuredwidth () {Getcontentview (). Measure (View.MeasureSpec.UNSPEC
Ified, View.MeasureSpec.UNSPECIFIED);
int popwidth = Getcontentview (). Getmeasuredwidth ();
return popwidth;
}
}
View_popup_window.xml
<?xml version= "1.0" encoding= "Utf-8"?> <com.yuyh.library.bubblerelativelayout xmlns:android=
" Http://schemas.android.com/apk/res/android "
xmlns:app=" Http://schemas.android.com/apk/res-auto
" Android:id= "@+id/brlbackground"
android:layout_width= "wrap_content"
android:layout_height= "WRAP_" Content "
android:background=" @android: color/transparent "
app:cornerradius=" "
app:halfbaseofleg=" 18DP "
app:padding=" 18DP "
app:shadowcolor=" #64000000 "
app:strokewidth=" 5 ">
</ Com.yuyh.library.bubblerelativelayout>
Call
Bubblepopupwindow Lefttopwindow = new Bubblepopupwindow (mainactivity.this);
View Bubbleview = inflater.inflate (R.layout.layout_popup_view, null);
TextView tvcontent = (TextView) Bubbleview.findviewbyid (r.id.tvcontent);
Tvcontent.settext ("HelloWorld");
Lefttopwindow.setbubbleview (Bubbleview); Set the bubble content
lefttopwindow.show (view, Gravity.bottom, 0);//Show the Bounce window
Depend on
dependencies {
compile ' com.yuyh.bubble:library:1.0.0 '
}
Project Address: Https://github.com/smuyyh/BubblePopupWindow
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.