创建一个自定义 Drawable 并将其用作您要放入文本或其他视图的任何容器的背景。
您将需要修改背景的填充以考虑气泡的指针。
下面的代码允许您将指针的对齐方式设置为左对齐、居中对齐或右对齐。
这只是一个基本版本,仅供您参考。您可以轻松地添加气泡颜色的设置器,或者向“mPaint”添加描边属性以获得额外的灵活性。
public class BubbleDrawable extends Drawable {
// Public Class Constants
////////////////////////////////////////////////////////////
public static final int LEFT = 0;
public static final int CENTER = 1;
public static final int RIGHT = 2;
// Private Instance Variables
////////////////////////////////////////////////////////////
private Paint mPaint;
private int mColor;
private RectF mBoxRect;
private int mBoxWidth;
private int mBoxHeight;
private float mCornerRad;
private Rect mBoxPadding = new Rect();
private Path mPointer;
private int mPointerWidth;
private int mPointerHeight;
private int mPointerAlignment;
// Constructors
////////////////////////////////////////////////////////////
public BubbleDrawable(int pointerAlignment) {
setPointerAlignment(pointerAlignment);
initBubble();
}
// Setters
////////////////////////////////////////////////////////////
public void setPadding(int left, int top, int right, int bottom) {
mBoxPadding.left = left;
mBoxPadding.top = top;
mBoxPadding.right = right;
mBoxPadding.bottom = bottom;
}
public void setCornerRadius(float cornerRad) {
mCornerRad = cornerRad;
}
public void setPointerAlignment(int pointerAlignment) {
if (pointerAlignment < 0 || pointerAlignment > 3) {
Log.e("BubbleDrawable", "Invalid pointerAlignment argument");
} else {
mPointerAlignment = pointerAlignment;
}
}
public void setPointerWidth(int pointerWidth) {
mPointerWidth = pointerWidth;
}
public void setPointerHeight(int pointerHeight) {
mPointerHeight = pointerHeight;
}
// Private Methods
////////////////////////////////////////////////////////////
private void initBubble() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mColor = Color.RED;
mPaint.setColor(mColor);
mCornerRad = 0;
setPointerWidth(40);
setPointerHeight(40);
}
private void updatePointerPath() {
mPointer = new Path();
mPointer.setFillType(Path.FillType.EVEN_ODD);
// Set the starting point
mPointer.moveTo(pointerHorizontalStart(), mBoxHeight);
// Define the lines
mPointer.rLineTo(mPointerWidth, 0);
mPointer.rLineTo(-(mPointerWidth / 2), mPointerHeight);
mPointer.rLineTo(-(mPointerWidth / 2), -mPointerHeight);
mPointer.close();
}
private float pointerHorizontalStart() {
float x = 0;
switch (mPointerAlignment) {
case LEFT:
x = mCornerRad;
break;
case CENTER:
x = (mBoxWidth / 2) - (mPointerWidth / 2);
break;
case RIGHT:
x = mBoxWidth - mCornerRad - mPointerWidth;
}
return x;
}
// Superclass Override Methods
////////////////////////////////////////////////////////////
@Override
public void draw(Canvas canvas) {
mBoxRect = new RectF(0.0f, 0.0f, mBoxWidth, mBoxHeight);
canvas.drawRoundRect(mBoxRect, mCornerRad, mCornerRad, mPaint);
updatePointerPath();
canvas.drawPath(mPointer, mPaint);
}
@Override
public int getOpacity() {
return 255;
}
@Override
public void setAlpha(int alpha) {
// TODO Auto-generated method stub
}
@Override
public void setColorFilter(ColorFilter cf) {
// TODO Auto-generated method stub
}
@Override
public boolean getPadding(Rect padding) {
padding.set(mBoxPadding);
// Adjust the padding to include the height of the pointer
padding.bottom += mPointerHeight;
return true;
}
@Override
protected void onBoundsChange(Rect bounds) {
mBoxWidth = bounds.width();
mBoxHeight = getBounds().height() - mPointerHeight;
super.onBoundsChange(bounds);
}
}
Usage
下面的示例展示了如何使用 BubbleDrawable。
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout linearLayout = (LinearLayout)findViewById(R.id.myLayout);
BubbleDrawable myBubble = new BubbleDrawable(BubbleDrawable.CENTER);
myBubble.setCornerRadius(20);
myBubble.setPointerAlignment(BubbleDrawable.RIGHT);
myBubble.setPadding(25, 25, 25, 25);
linearLayout.setBackgroundDrawable(myBubble);
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/myLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some Other Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
</RelativeLayout>