I have a Custom View that extends RelativeLayout with overridden onDraw() method so that it looks like a message bubble. This View is in the LinearLayout. When I try to fill this custom View with content, part of its shape is pushed out of the LinearLayout. How to prevent this behaviour?How to prevent this behaviour?
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:id="#+id/chat_message_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="center_vertical"
android:padding="10dp"
android:text="2:46pm"
android:textSize="#dimen/splash_4_user_name_text_size" />
<com.mypackage.RightBasedMessage
android:id="#+id/chat_message_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="#dimen/splash_3_comment_padding"
android:paddingLeft="#dimen/splash_3_comment_end_padding"
android:paddingRight="#dimen/chat_message_field_beginning_padding"
android:paddingTop="#dimen/splash_3_comment_padding">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hi :)"
android:textColor="#color/white_text_color" />
</com.mypackage.RightBasedMessage>
</LinearLayout>
Here is my Custom View:
public class RightBasedMessage extends RelativeLayout {
private Paint paint;
private Path path;
private Point pointleftTop;
private Point pointRightTop;
private Point pointRightBottom;
private Point pointLeftBottom;
private float corner;
private Context context;
private int color = R.color.chat_my_message_field_color;
public RightBasedMessage(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
corner = getResources().getDimension(R.dimen.message_container_corner);
paint = new Paint();
path = new Path();
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.FILL);
this.setWillNotDraw(false);
}
public void setMessageBackground(int color){
this.color = color;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
pointRightTop = new Point(width-(int)corner, (int)corner/2);
pointRightBottom = new Point(width-(int)corner, height);
pointLeftBottom = new Point(0, height);
pointleftTop = new Point(0, 0);
path.reset();
path.moveTo(corner, 0);
path.lineTo(width, 0);
path.quadTo(pointRightTop.x, pointRightTop.y, width-corner, corner+corner/2);
path.lineTo(width-corner, height-corner);
path.quadTo(pointRightBottom.x, pointRightBottom.y, width - corner*2, height);
path.lineTo(corner, height);
path.quadTo(pointLeftBottom.x, pointLeftBottom.y, 0, height-corner);
path.lineTo(0, corner);
path.quadTo(pointleftTop.x, pointleftTop.y, corner, 0);
paint.setColor(ContextCompat.getColor(context, color));
canvas.drawPath(path, paint);
path.close();
}
}
have you tried this?
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
>
Related
This is wanted layout:
Layout
I'm stuck with this for a long time. Trying to rotate somekind buttons to mask other one and other ways like with:
<rotate
android:fromDegrees="45"
android:toDegrees="45"
android:pivotX="-40%"
android:pivotY="87%" />
How to write code for this layout, buttons need to be custom shaped, not to be able with clicking around them, to achieve clicking same?
EDIT I tried Making a triangle shape using xml definitions? , Creating a triangular shaped button for android application
but this what i got: http://i.stack.imgur.com/X88P0.png
Here is the code of TriangleButton which draw triangle and react on clickEvent() only if your finger position in triangle zone. Here you can set colors(normal and pressed):
Class:
public class TriangleButton extends Button {
private final float RADIUS = 50.0f;
private boolean mIsPressed;
private Region mPathRegion;
private final Path mPath = new Path();
private final Paint mNormalPaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setStyle(Style.FILL);
setPathEffect(new CornerPathEffect(RADIUS));
}
};
private final Paint mPressedPaint = new Paint(Paint.ANTI_ALIAS_FLAG) {
{
setDither(true);
setStyle(Style.FILL);
setPathEffect(new CornerPathEffect(RADIUS));
}
};
public TriangleButton(final Context context) {
this(context, null);
}
public TriangleButton(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public TriangleButton(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWillNotDraw(false);
setBackgroundColor(Color.TRANSPARENT);
setColors(Color.RED, Color.GRAY);
}
public void setColors(final int color, final int pressed) {
mNormalPaint.setColor(color);
mPressedPaint.setColor(pressed);
}
#Override
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Set triangle
mPath.reset();
mPath.moveTo(0.0f, h);
mPath.lineTo(w / 2.0f, 0.0f);
mPath.lineTo(w, h);
mPath.close();
// Create region for touch detecting
final RectF rectF = new RectF();
mPath.computeBounds(rectF, true);
mPathRegion = new Region();
mPathRegion.setPath(
mPath,
new Region(
(int) rectF.left,
(int) rectF.top,
(int) rectF.right,
(int) rectF.bottom)
);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mPathRegion.contains((int) event.getX(), (int) event.getY())) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsPressed = true;
break;
case MotionEvent.ACTION_UP:
mIsPressed = false;
performClick();
break;
case MotionEvent.ACTION_CANCEL:
mIsPressed = false;
break;
}
postInvalidate();
} else {
mIsPressed = false;
postInvalidate();
return false;
}
postInvalidate();
return true;
}
#Override
protected void onDraw(final Canvas canvas) {
canvas.drawPath(mPath, mIsPressed ? mPressedPaint : mNormalPaint);
super.onDraw(canvas);
}
}
XML:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.user.timezonetest.TriangleButton
android:id="#+id/btn_bottom"
android:layout_width="300dp"
android:layout_height="250dp"
android:text="Second Button"
android:textColor="#000"
android:layout_gravity="center_horizontal"
android:gravity="bottom|center_horizontal"
android:padding="30dp"/>
<com.example.user.timezonetest.TriangleButton
android:id="#+id/btn_top"
android:layout_width="180dp"
android:layout_height="160dp"
android:text="First Button"
android:textColor="#000"
android:layout_gravity="center_horizontal"
android:gravity="bottom|center_horizontal"
android:layout_margin="30dp"
android:padding="30dp"/>
</FrameLayout>
Code:
final TriangleButton bottomButton = (TriangleButton) findViewById(R.id.btn_bottom);
final TriangleButton topButton = (TriangleButton) findViewById(R.id.btn_top);
bottomButton.setColors(Color.RED, Color.GRAY);
topButton.setColors(Color.YELLOW, Color.GRAY);
You can define two Button with link you provide and then put both of them in same FrameLayout with something like following code :
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="300dp"
android:layout_height="300dp" >
<Button
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#drawable/rectangle_1" />
<Button
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#drawable/rectangle_2" />
/>
Create rectangle_1 and rectangle_2 with links in comment.
I am using a custom layout for having rounded corners.Please find the code for the custom layout.
public class RoundedCornerLayout extends FrameLayout {
private final static float CORNER_RADIUS = 20.0f;
private Bitmap maskBitmap;
private Paint paint, maskPaint;
private float cornerRadius;
public RoundedCornerLayout(Context context) {
super(context);
init(context, null, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs, defStyle);
}
private void init(Context context, AttributeSet attrs, int defStyle) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setWillNotDraw(false);
}
#Override
public void draw(Canvas canvas) {
Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas offscreenCanvas = new Canvas(offscreenBitmap);
super.draw(offscreenCanvas);
if (maskBitmap == null) {
maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
}
offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
}
private Bitmap createMask(int width, int height) {
Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
Canvas canvas = new Canvas(mask);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
canvas.drawRect(0, 0, width, height, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);
return mask;
}
}
I have included a ListView inside this layout. But the ListView is not scrolling when added inside this layout. But if I change the layout to a FrameLayout the ListView scroll will work.
The XML layout I am using,
<com.mob.utils.RoundedCornerLayout 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"
">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#E8E9E8">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="60dp"
android:background="#F9B541">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="Select Recepients"
android:textColor="#ffffff"
android:textSize="8pt"
android:id="#+id/textView9"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<info.hoang8f.android.segmented.SegmentedGroup
android:id="#+id/friendSegmented"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"
android:layout_centerInParent="true">
<RadioButton
android:id="#+id/rdBtn_Facebook"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Facebook"
style="#style/RadioButton" />
<RadioButton
android:id="#+id/rdBtn_Email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Email"
style="#style/RadioButton" />
</info.hoang8f.android.segmented.SegmentedGroup>
</RelativeLayout>
<LinearLayout
android:id="#+id/recepientContainer"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"></LinearLayout>
</LinearLayout>
</com.mob.utils.RoundedCornerLayout>
How to fix this?
Thanks
I have the following custom View (basically is a View containing an image, on that image you can draw rectangles).
public class MyView extends View {
public Bitmap mBitmap;
public Canvas mCanvas;
public Rect mPath;
public Paint mBitmapPaint;
public Paint mPaint;
public MyView(Context c) {
super(c);
Log.e("","call first constructor");
mPath = new Rect();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.b6p1).copy(Bitmap.Config.ARGB_8888, true);
mCanvas.drawBitmap(bitmap, 0, 0, mBitmapPaint);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawRect(mPath, mPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float left;
float right;
float bottom;
float top;
if (x < mX) {
left = x;
right = mX;
} else {
left = mX;
right = x;
}
if (y < mY) {
top = y;
bottom = mY;
} else {
top = mY;
bottom = y;
}
mPath = new Rect((int) left, (int) top, (int) right, (int) bottom);
}
private void touch_up() {
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}
Now I want to add this to my Layout,
the layout is the following,
and i want to replace the ImageView with my the MyView View.
<LinearLayout 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:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:orientation="vertical"
android:weightSum="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9" >
<HorizontalScrollView
android:id="#+id/horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:id="#+id/vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ImageView>
</ScrollView>
</HorizontalScrollView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.1"
android:background="#android:color/darker_gray" >
<Button
android:id="#+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LEFT" />
<Button
android:id="#+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RIGHT" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2"
android:background="#android:color/darker_gray"
android:orientation="vertical" >
<Button
android:id="#+id/up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="UP" />
<Button
android:id="#+id/down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DOWN" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
I have tried:
<LinearLayout 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:orientation="horizontal" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="1" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:orientation="vertical"
android:weightSum="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.9" >
<HorizontalScrollView
android:id="#+id/horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ScrollView
android:id="#+id/vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.test.MyView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ScrollView>
</HorizontalScrollView>
</LinearLayout>
But NO SUCCESS,
the image that can be drawn upon does not show...
It show a blank field...
You should override onMeasure() in your custom view.Do something like this :
#Override
public void onMeasure(int widthSpecs, int heightSpecs) {
super.onMeasure(widthSpecs, heightSpecs);
setMeasuredDimension(mDisplayUtils.getScreenWidth(), mDisplayUtils.getScreenHeight());
}
or whatever values you want.
Another thing which I can think of is that you are initialising your variables on your main constructor. Make it like this way :
public MyView(Context c) {
super(c);
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init(){
Log.e("","call first constructor");
mPath = new Rect();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
I need to have dotted lines in my editext field. Here is what i have tried so far. But didn't reach my goal. It displays nothing. Why dotted lines are missing? Where i'am going wrong?
EditText filed in main.xml
<view
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
class="com.xxx.yyy.MainActivity$LinedEditText"
android:background="#android:color/transparent"
android:inputType="textEmailAddress"
android:maxHeight="30dp"
android:singleLine="true"
android:minHeight="30dp"
android:textSize="13dp" />
Inside MainActivity..
public static class LinedEditText extends EditText {
private Rect mRect;
private Paint mPaint;
// we need this constructor for LayoutInflater
public LinedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mRect = new Rect();
mPaint = new Paint();
mPaint.setARGB(255, 0, 0,0);
mPaint.setStyle(Style.STROKE);
mPaint.setPathEffect(new DashPathEffect(new float[] {1,2}, 0));
mPaint.setColor(Color.RED);
}
#Override
protected void onDraw(Canvas canvas) {
int count = getLineCount();
for (int i = 0; i < count; i++) {
int baseline = getLineBounds(i, mRect);
canvas.drawLine(mRect.left, baseline + 1, mRect.right, baseline + 1, mPaint);
}
super.onDraw(canvas);
}
}
Add this to your view xml
android:ellipsize="end";
Hope it helps...
I use this to have stike through a textView
textView.setPaintFlags(textView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
but now I wanna personalize the color and rotate it 45° to fit the diagonal of the content.
What I tied:
I though about extending the textview widget and override onDraw method .. but I'm very beginner at designing ...
so any help how to draw the red(color) rotated line on the textView ?
adding to Mayani's response
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(strikeThroughColor);
paint.setStyle(Paint.Style.FILL);
paint.setFakeBoldText(true);
paint.setStrikeThruText(true);
paint.setStrokeWidth(strikeThroughWidth);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
super.onDraw(canvas);
float width = getWidth();
float height = getHeight();
canvas.drawLine(width / 10, height / 10, (width - width / 10), (height - height / 10), paint);
}
For that, follow the below steps:
Create a custom TextView by extending View class
Declare this custom textview inside XML layout same like we do for TextView, Button widgets.
For example:
class CustomTextView extends View {
private int mColor;
private int mRotationAngle, mRotationW, mRotationH;
private String mText;
public CustomTextView(Context context) {
super(context);
// set default parameters
mColor = Color.WHITE;
mRotationAngle = 0;
}
public void SetColor(int newcolor) {
mColor = newcolor;
this.invalidate();
}
public void SetRotation(int newangle, int neww, int newh) {
mRotationAngle = newangle;
mRotationW = neww;
mRotationH = newh;
this.invalidate();
}
public void SetText(String newtext) {
mText = newtext;
this.invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
canvas.rotate(mRotationAngle,mRotationW,mRotationH);
canvas.drawText(mText, 0, 0, paint);
super.onDraw(canvas);
}
}
Update:
Check for Specifying “strikethrough” on a section of TextView text
Using below approach you can achieve this functionality without messing with the UI in your java code:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true">
<TextView
android:id="#+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:text="$99"
android:textSize="12sp" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_centerVertical="true"
android:layout_alignLeft="#+id/textview1"
android:layout_alignRight="#+id/textview1"
android:background="#color/fav_dark_red_color" />
</RelativeLayout>