2

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: https://i.stack.imgur.com/X88P0.png

Community
  • 1
  • 1
Jeste
  • 37
  • 10
  • Possible duplicate of [Making a triangle shape using xml definitions?](http://stackoverflow.com/questions/2517589/making-a-triangle-shape-using-xml-definitions) – Amir Feb 05 '16 at 21:54
  • http://stackoverflow.com/questions/25396194/creating-a-triangular-shaped-button-for-android-application – Amir Feb 05 '16 at 21:54
  • I tried all of it and got this http://i.stack.imgur.com/X88P0.png – Jeste Feb 05 '16 at 21:55
  • Create two bottom with different size and Put both of them in **FrameLayout** your problem will be fixed – Amir Feb 05 '16 at 21:57
  • what do mean not working ? what is your problem exactly ? can you explain more ? – Amir Feb 05 '16 at 22:07
  • You could probably achieve clicking only inside the triangles, by creating your own `OnTouchListener` and measure where the click is actually happening - if it's actually happening inside the triangle. – Darwind Feb 05 '16 at 22:11
  • @Darwind if just set **clickable** true for smaller button it will works too :) – Amir Feb 05 '16 at 22:28
  • @Amir It will still be possible to click the areas around the triangles that lies inside the triangles outer square. A view or button is a rectangle by default and doesn't change because you change the background of the button. – Darwind Feb 05 '16 at 23:07

2 Answers2

1

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.

Amir
  • 16,067
  • 10
  • 80
  • 119
  • I hacked now somehow, but i use relativelayout. In first i used code i put in question for rotation then i found in your second link other values that i didn't try. Do you mean Button by Bottom? – Jeste Feb 05 '16 at 22:14
  • Yes , I mean Button :D – Amir Feb 05 '16 at 22:19
  • I tried and i got just mask, not button that have figure like triangle – Jeste Feb 06 '16 at 15:31
1

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):

enter image description here

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);
GIGAMOLE
  • 1,274
  • 1
  • 11
  • 17
  • But i want, button that have figure like triangle, not just mask – Jeste Feb 06 '16 at 15:30
  • 1
    Thanks man. This what i got http://imgur.com/M40SzA1 when i select button in preview, and also in real app, i tried with toast msg, it responds all around triangle – Jeste Feb 06 '16 at 16:31
  • I can't understand, that no one have complains about that issue, on attached links. Maybe i something did wrong – Jeste Feb 06 '16 at 19:20
  • Whats wrong again? Tell me what you need and ill try to catch it. – GIGAMOLE Feb 06 '16 at 19:45
  • I'm not so sure about this android.graphics.Region. Does when .setPath, mPath is offset to *second argument, so we can then in ( .contains ) checks does click is performed in area that contain that offset --- which (offset) is contained in *second argument? Why didn't simply check does it contains touched area just with android.graphics.Path, i think, cause there is not method, or this must be done with region? Can u explain me in short hand, how this works? – Jeste Feb 07 '16 at 17:49
  • Why you have "m" like prefix on "casual" variables, and not on "constants", i new to naming variables i thinks so, so i wanna hear if u can tell me what logic is under "m"? – Jeste Feb 07 '16 at 19:19
  • "m" preffix is like "my" - the global variable of class. "s" preffix is "static". Constants does not have any preffix and all in upper case. – GIGAMOLE Feb 07 '16 at 21:35
  • Cause Path does`nt have method contains(). So we need to set path to the Region and later check for it match in onTouch(). – GIGAMOLE Feb 07 '16 at 21:48
  • I will waiting for yor level up. – GIGAMOLE Feb 09 '16 at 17:12
  • Can u review this question, http://stackoverflow.com/questions/35612825/how-to-adjust-image-for-custom-imagebutton ? – Jeste Feb 24 '16 at 20:52