Android vertical Seekbar thumb alignment is not proper - android

I have a LinearLayout with vertical seekbars in it. For vertical seek bar I am using custom class. While using android:layout_weight="1" seekbar thumb alignment is not proper.
verticalseekbar.xml
<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" >
<com.example.verticalseekbardemo.VerticalSeekBar
android:id="#+id/seekBar1"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:progress="50" />
<com.example.verticalseekbardemo.VerticalSeekBar
android:id="#+id/seekBar2"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:progress="30" />
<com.example.verticalseekbardemo.VerticalSeekBar
android:id="#+id/seekBar3"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:progress="10" />
<com.example.verticalseekbardemo.VerticalSeekBar
android:id="#+id/seekBar4"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1" />
<com.example.verticalseekbardemo.VerticalSeekBar
android:id="#+id/seekBar5"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:progress="80" />
</LinearLayout>
VerticalSeekBar.java
public class VerticalSeekBar extends SeekBar{
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
public synchronized void setProgress(int progress) // it is necessary for
// calling setProgress
// on click of a button
{
super.setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
setProgress(getMax()
- (int) (getMax() * event.getY() / getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}
Did anyone encounter this kind of issue.
Thanks.

I had the same issue. The only way to solve it, was putting each seekbar into a FrameLayout, like this:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<com.example.verticalseekbardemo.VerticalSeekBar
android:id="#+id/seekBar1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:progress="50" />
</FrameLayout>
I hope help you.

Here is an example
<LinearLayout
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:layout_gravity="center"
android:gravity="center"
android:background="#ffffff">
<com.example.yourpackgename_where_VerticalSeekbar_is_define.VerticalSeekBar
android:id="#+id/first_seekbar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:progress="50" />
</LinearLayout>
To add the 5 seek bar i would suggest make a LinearLayout with horizontal orientation with weight sum of 5 and then inside the layout copy the above code 5 time with different ids

Instead of using vertical seekbar add android:rotation="90" in your normal seekbar code.
Ex:-
<SeekBar
android:layout_width="200dp"
android:layout_height="wrap_content"
android:max="50"
android:id="#+id/rightturn"
android:layout_marginTop="80dp"
**android:rotation="90"**
/>

If you'd like to use your custom VerticalSeekBar, I think the issue is that the Canvas needs to be rotated in the center to get the desired effect, although I could be wrong.
int centerX;
int centerY;
protected void onDraw(Canvas c) {
c.translate(centerY, centerX);
c.rotate(-90);
super.onDraw(c);
}
#Override
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
super.onSizeChanged(width, height, oldw, oldh);
centerX = width / 2;
centerY = height / 2;
}

i have same issue and i solve this by adding
android:maxHeight="300dp"
to seekbar in layout file.
Hope this help you.

Related

Why are buttons making my canvas drawing like hexagon shape in Android?

I have a strange problem I'm creating a canvas drawing app in Android that has lots of buttons in xml file. The problems is when I draw a circle with all those buttons included in the file it's never a smooth circle it's full of corners like hexagon shape but when I exclude buttons may be leaving in one or two, it draws a perfect smooth circle. I have tried to split the file into three so I've included them using but still same result. Can someone please enlighten me what am I do wrong.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--First Draw -->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageButton
android:id="#+id/nav_one"
android:layout_width="30dp"
android:layout_height="60dp"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"
android:background="#drawable/ic_tab_res_bkg"/>
<ImageButton
android:id="#+id/nav_two"
android:layout_width="30dp"
android:layout_height="60dp"
android:layout_marginTop="200dp"
android:background="#drawable/ic_tab_tools_bkg"/>
</LinearLayout>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/resource_bank"
android:layout_width="350dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/background_light"
android:dividerHeight="0dp"
android:background="#f4f1f1"
/>
<ListView android:id="#+id/tools"
android:layout_width="350dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:choiceMode="singleChoice"
android:divider="#android:color/background_light"
android:dividerHeight="0dp"
android:background="#dedada"/>
</android.support.v4.widget.DrawerLayout>
<RelativeLayout
android:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" >
<xxxxx.xxxxxx.xxxx.xxxxxx.DrawView
android:id="#+id/canvas_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/canvas_view">
<!-- Pen icons -->
<include layout="#layout/activity_pen_color" android:id="#+id/pen_color" />
<include layout="#layout/activity_pen_style" android:id="#+id/pen_style" />
<!-- Navigation bar icons -->
<ImageView
android:id="#+id/icon_bar"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_gravity="bottom"
android:background="#drawable/icon_bar_bkg"
/>
<Button
android:id="#+id/ic_select"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="150dp"
android:layout_marginTop="60dp"
android:elevation="1dp"
android:background="#drawable/ic_select_bkg"/>
<TextView
android:id="#+id/text_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="150dp"
android:layout_marginTop="90dp"
android:text="Select"
android:textColor="#color/colorAccent"
/>
<Button
android:id="#+id/ic_pens"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="200dp"
android:layout_marginTop="60dp"
android:elevation="1dp"
android:background="#drawable/ic_pen_bkg"/>
<TextView
android:id="#+id/text_pens"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="200dp"
android:layout_marginTop="90dp"
android:text="Pen"
android:textColor="#color/colorAccent"
/>
</FrameLayout>
</RelativeLayout>
My DrawView
public class DrawView extends View {
private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private SparseArray<Path> paths;
public DrawView(Context context) {
super(context);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupDrawing();
}
private void setupDrawing() {
paths = new SparseArray<>();
drawPaint = new Paint();
drawPaint.setColor(Color.BLACK);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(9);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
for (int i=0; i<paths.size(); i++) {
canvas.drawPath(paths.valueAt(i), drawPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int id = event.getPointerId(index);
Path path;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
path = new Path();
path.moveTo(event.getX(index), event.getY(index));
paths.put(id, path);
break;
case MotionEvent.ACTION_MOVE:
for (int i=0; i<event.getPointerCount(); i++) {
id = event.getPointerId(i);
path = paths.get(id);
if (path != null) path.lineTo(event.getX(i), event.getY(i));
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
path = paths.get(id);
if (path != null) {
drawCanvas.drawPath(path, drawPaint);
paths.remove(id);
}
break;
default:
return false;
}
invalidate();
return true;
}
/**
* change path color here
*/
public void setPathColor(int color) {
drawPaint.setColor(color);
}
}
Answer
I take it that you are drawing this circle with your finger, and that when a lot of extra buttons are present, you notice that the lines you draw with your finger become "less smooth".
This is related to the app's screen refresh rate. When your app has to spend lots of time drawing all those extra buttons, it has fewer opportunities to get MotionEvents. With fewer MotionEvents, there are fewer points in your shape, and it takes longer line segments to connect them.
Suggested fix
The recommended approach is to stop those button views from being invalidated (an assumption on my part) every time onTouchEvent() gets called. From your code, I can't immediately see why they would be invalidated, but it may be that your DrawView underlies the buttons you are adding, thus whenever the DrawView is invalidate()-ed, the system must re-compose it with the buttons. You could move the DrawView so that it's by itself. Adding an opaque background to your button container(s) may help as well, b/c the system would have to do fewer alpha calculations.
You must have a lot of buttons... you may want to do some performance profiling to determine exactly what's taking so long.

How to delete Additional space ImageView in Android

I want use ImageView in my project, but it shows additional space in the layout. How can I remove the additional space?
This image shows the problem:
XML code:
<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="wrap_content"
tools:context="com.tellfa.smsbox.activities.Dialog_image_show">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:src="#drawable/cover_menu_bg" />
</RelativeLayout>
</RelativeLayout>
I don't want use android:scaleType="centerCrop".
Use the imageview like these
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/icon"
android:id="#+id/imv"
android:scaleType="fitCenter" />
Try this custom ImageView class
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Drawable d = getDrawable();
if(d!=null){
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
}else{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
And use this class as below
<your_package.ResizableImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:src="#drawable/cover_menu_bg" />
For anyone looking for solution for both orientations. Here is my approach with samples:
First, my xml:
<?xml version="1.0" encoding="utf-8"?>
<com.example.michal.fillimageview.CustomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#f0f000"
android:orientation="vertical">
<com.example.michal.fillimageview.ResizableImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:adjustViewBounds="true"
android:src="#drawable/p600_900" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
android:text="Hello World!"
android:textColor="#android:color/holo_red_dark"
android:textSize="30sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/background_dark"
android:text="Hello World!"
android:textColor="#android:color/holo_red_dark"
android:textSize="30sp" />
</com.example.michal.fillimageview.CustomLinearLayout>
Class:
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
// ceil not round - avoid thin vertical gaps along the left/right edges
int width = View.MeasureSpec.getSize(widthMeasureSpec);
int height = View.MeasureSpec.getSize(heightMeasureSpec);
if (height > width) {//portrait
if (d.getIntrinsicWidth() > d.getIntrinsicHeight()) {
height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
} else {
width = (int) Math.ceil((float) height * (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight());
setMeasuredDimension(width, height);
}
} else {//landscape
width = (int) Math.ceil((float) height * (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight());
setMeasuredDimension(width, height);
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
Samples for specific images:
600x900 portrait
600x900 landscape
800x600 portrait
800x600 landscape

Combining layout_weight and maxHeight

I'm quite new to Android programming and I'm stuck on an simple problem.
I have a basic homepage with some buttons and a logo. I use a LinearLayout and the layout_weight attribute to distribute all the components.
Here is my code :
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="iut.project.findmeapp.MainActivity" >
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:contentDescription="#string/description_logo"
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
android:layout_margin="#dimen/img_margin"
android:src="#drawable/ic_launcher" />
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:layout_marginTop="#dimen/button_margin_vertical"
android:layout_marginBottom="#dimen/button_margin_vertical"
android:layout_weight="1"
android:text="#string/last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="#dimen/null_height"
android:gravity="center"
android:layout_weight="0.5"
android:layout_margin="#dimen/tw_margin"
android:text="#string/copyright" />
</LinearLayout>
(Note : #dimen/null_height is 0dp)
My problem is that I want the image to scale with the size of the screen, but I don't want it pixelated : I have set a maximum height of 200px.
The following lines don't seem to work, because the image has no limit and totally ignores the maxHeight attribute.
android:layout_weight="1"
android:maxHeight="#dimen/img_maxHeight"
Actually it looks like this (example image) :
It works perfectly, but when I set maxHeight to 10px for example, nothing changes.
How can I achieve this ? I highly prefer to use a LinearLayout.
Thank you in advance.
Thanks to Evripidis Drakos for pointing me in the right direction. Just need a check to only set the max height if it's actually required.
public class MaxHeightImageView extends ImageView {
public static final int MAX_HEIGHT_NOT_SET = -1;
public static final int INDEX_MAX_HEIGHT = 0;
private static final int[] STYLE_ATTRIBUTE_ARRAY = {
android.R.attr.maxHeight,
};
private int myMaxHeight;
public MaxHeightImageView(Context context) {
super(context);
init(context, null);
}
public MaxHeightImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public MaxHeightImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = MeasureSpec.getSize(heightMeasureSpec);
if(MAX_HEIGHT_NOT_SET != myMaxHeight && size > myMaxHeight) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(myMaxHeight, MeasureSpec.AT_MOST);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private void init(Context context, AttributeSet attrs) {
if(context != null) {
TypedArray ta = context.obtainStyledAttributes(attrs,
STYLE_ATTRIBUTE_ARRAY);
myMaxHeight = ta.getDimensionPixelSize(INDEX_MAX_HEIGHT, 0);
} else {
myMaxHeight = MAX_HEIGHT_NOT_SET;
}
}
}
I dont think that you can combine layout_weight with maxHeight.
You could try subclassing ImageView to override the onMeasure method like so:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(200, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
if u want to set exact height for your image u should use weightSum property with weight
edit:
for fixed height do not give weight for imageview just take parent layout for imageview then add weight for that linear layout(parent layout) and for imageview give height as wrap content and maxHeight. when u use weight with height="0dp" the content will capture the whole height so it will ignore maxHeight.
try this
<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="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:weightSum="5"
tools:context="iut.project.findmeapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="#+id/activityMainAppLogoIv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:contentDescription="#string/quantity_hint"
android:maxHeight="200px"
android:src="#drawable/ic_launcher" />
</LinearLayout>
<Button
android:id="#+id/activityMainMyEventsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_events" />
<Button
android:id="#+id/activityMainMyContactsBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="my_contacts" />
<Button
android:id="#+id/activityMainLastNotifBtn"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="last_notification" />
<TextView
android:id="#+id/activityMainCopyrightTv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".5"
android:gravity="center"
android:text="copyright" />
</LinearLayout>

Scrolling the custom views - Android

Below is the image of the menu I need to make.
I have drawn the triangles using canvas in custom views. I also need to scroll this menu, when custom views are added in the scroll view it takes each View as a rectangular item not allowing the triangles to be drawn like this.
Is there anyway to achieve this?
Thanks in advance.
At first you must create 2 custom views, with different draws of triangles. Then in your RelativeLayout or another create those triangles and set the, negative margin_top value for correct presentation, like in my example:
So, now lets look at code.
Dont critic my code. It`s just example for you without true OOP structure :)
CustomShapeLeft.class:
/**
* Created by gigamole on 07.02.15.
*/
public class CustomShapeLeft extends RelativeLayout {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
int backgroundColor;
int viewWidth; // width of parent(CustomShape layout)
int viewHeight;
public CustomShapeLeft(Context context) {
super(context);
this.setWillNotDraw(false);
}
public CustomShapeLeft(Context context, AttributeSet attrs) {
super(context, attrs);
this.setWillNotDraw(false);
TypedArray ta = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.background});
this.backgroundColor = ((ColorDrawable) ta.getDrawable(0)).getColor();
this.setBackgroundColor(Color.TRANSPARENT);
}
public CustomShapeLeft(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.setWillNotDraw(false);
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
super.onSizeChanged(xNew, yNew, xOld, yOld);
viewWidth = xNew;
viewHeight = yNew;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Path path = new Path();
Point[] points = new Point[3];
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(backgroundColor);
paint.setStyle(Paint.Style.FILL);
points[0] = new Point(0, 0);
points[1] = new Point(viewWidth, (viewHeight / 2));
points[2] = new Point(0, (viewHeight));
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(points[0].x, points[0].y);
path.lineTo(points[1].x, points[1].y);
path.lineTo(points[2].x, points[2].y);
path.close();
canvas.drawPath(path, paint);
}
public boolean isTouched(final float X, final float Y){
final Polygon p = new Polygon(points);
return p.contains(X, Y);
}
}
Method isTouched() need for know when the user tap on shape, but not on View, cause when on last, its problematic to take correct action, cause they lay down like layer-layer-layer system.
This method get the position of tap and calculate is on shape or not. In your way you will dont have onClickListener, just onTouchListener.
CustomShapeRight.class:
They are almost similar, but different draw methods:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(backgroundColor);
paint.setStyle(Paint.Style.FILL);
points[0] = new Point(viewWidth, 0);
points[1] = new Point(0, (viewHeight / 2));
points[2] = new Point(viewWidth, (viewHeight));
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(points[0].x, points[0].y);
path.lineTo(points[1].x, points[1].y);
path.lineTo(points[2].x, points[2].y);
path.close();
canvas.drawPath(path, paint);
}
Layout.xml:
<null_anal.customshape.CustomShapeLeft
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/triangle_1"
android:background="#android:color/holo_red_dark">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="22dp"
android:padding="5dp"
android:textColor="#android:color/black"
android:text="MEN"
android:background="#android:color/transparent"/>
</null_anal.customshape.CustomShapeLeft>
<null_anal.customshape.CustomShapeRight
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/triangle_2"
android:layout_marginTop="-36dp"
android:background="#android:color/holo_orange_dark"
android:layout_below="#+id/triangle_1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="22dp"
android:layout_alignParentRight="true"
android:padding="5dp"
android:textColor="#android:color/black"
android:text="HOME"
android:background="#android:color/transparent"/>
</null_anal.customshape.CustomShapeRight>
<null_anal.customshape.CustomShapeLeft
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/triangle_3"
android:layout_marginTop="-36dp"
android:background="#android:color/holo_purple"
android:layout_below="#+id/triangle_2">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="22dp"
android:padding="5dp"
android:textColor="#android:color/black"
android:text="WOMEN"
android:background="#android:color/transparent"/>
</null_anal.customshape.CustomShapeLeft>
<null_anal.customshape.CustomShapeRight
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/triangle_4"
android:layout_marginTop="-36dp"
android:background="#android:color/holo_green_dark"
android:layout_below="#+id/triangle_3">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="22dp"
android:layout_alignParentRight="true"
android:padding="5dp"
android:textColor="#android:color/black"
android:text="ART"
android:background="#android:color/transparent"/>
</null_anal.customshape.CustomShapeRight>
<null_anal.customshape.CustomShapeLeft
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/triangle_5"
android:layout_marginTop="-36dp"
android:background="#android:color/holo_blue_dark"
android:layout_below="#+id/triangle_4">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="22dp"
android:padding="5dp"
android:textColor="#android:color/black"
android:text="KIDS"
android:background="#android:color/transparent"/>
</null_anal.customshape.CustomShapeLeft>
<null_anal.customshape.CustomShapeRight
android:layout_width="match_parent"
android:layout_height="70dp"
android:id="#+id/triangle_6"
android:layout_marginTop="-36dp"
android:background="#android:color/holo_blue_bright"
android:layout_below="#+id/triangle_5">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textSize="22dp"
android:layout_alignParentRight="true"
android:padding="5dp"
android:textColor="#android:color/black"
android:text="MUSIC"
android:background="#android:color/transparent"/>
</null_anal.customshape.CustomShapeRight>
And in activity set them onTouchListener():
CustomShapeRight customShapeRight = (CustomShapeRight) findViewById(R.id.triangle_6);
customShapeRight.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (((CustomShapeRight)v).isTouched(event.getX(), event.getY())) {
Toast.makeText(getApplicationContext(), ((TextView)((CustomShapeRight) v).getChildAt(0)).getText(), Toast.LENGTH_SHORT).show();
}
return false;
}
});
And all. I`d hope this will help you and with delete items "X" item in your layout you will deal with it alone. And thanks for cool question. Like it.

Android upside down a layout or rotate by 180

I am coding an Android game in which 2 players play at the same time. One player faces the phone in a normal way and the other faces it upside down.
As it is a quiz, I didn't use any canvas or graphics. It contains only 2 linear layouts and one of them is supposed to be upside down. For this I have used:
android:rotation="180"
for one of the layouts.
it showed upside down on the graphical view of my xml in Eclipse but when I run it on an emulator or a phone it is not inverted or rotated to 180 degrees.
XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<LinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:clipToPadding="false"
android:rotation="180">
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
</LinearLayout
Java Code
public class x extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
How can I rotate it without complication. I am presently using api level 15 but i have no restriction on API level.
I would suggest that you create a custom Layout that will handle the rotation on it's onDraw()
public class RotatedLinearLayout extends RotatedLinearLayout {
final boolean topDown;
public RotatedLinearLayout (Context context){
super(context);
}
public RotatedLinearLayout (Context context, AttributeSet attrs){
super(context, attrs);
}
public RotatedLinearLayout (Context context, AttributeSet attrs, int defStyle){
super(context, attrs,defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
#Override
protected void onDraw(Canvas canvas){
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if(topDown){
canvas.translate(getWidth(), 0);
canvas.rotate(180);
}else {
canvas.translate(0, getHeight());
canvas.rotate(-180);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
When you write your XML, use the VerticalRelativeLayout instead of the other layout you tried to create.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<path.to.package.RotatedLinearLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:clipToPadding="false"
>
<Button
android:id="#+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</path.to.package.RotatedLinearLayout >
</LinearLayout

Categories

Resources