0

I am building a XML layout for a piano keyboard, based on ImageButtons. The problem gets summarized with the following image:

my_xml_layout_try

I am aware that other similar questions have been posted, like this one. However, my approach disagrees with depending on Java to draw layouts, because I think, whenever possible, design issues should depend only on XML. There's also someone offering a template for a piano layout, but I prefer to do my own one.

That said, the point is: Is it possible to make the ImageButtons shown above "overlap" on purpose for making the black keys fit like they should, without depending on Java logic to achieve it? If not, is there a way to customize ImageButton objects to have a shape different than rectangular?

Here's the XML source, summarized:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <!-- first white key -->
    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:id="@+id/ck"
        android:src="@drawable/wk_c" />

    <!-- the BLACK key -->
    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:id="@+id/bk1"
        android:src="@drawable/bk" />

    <!-- next white key -->
    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:id="@+id/dk"
        android:src="@drawable/wk_d"
        android:adjustViewBounds="false" />

    <!-- ... and so on for the other keys -->
</LinearLayout>
SebasSBM
  • 860
  • 2
  • 8
  • 32
  • 1
    this with relative layout is much better – user210504 Aug 08 '15 at 23:58
  • You are right. I noticed it long ago thanks to the answers/comments below. Due to all what happened since I posted the question, I'm seriously considering editing it, or something... I have to think seriously about it on the next days – SebasSBM Aug 09 '15 at 00:00
  • I mean, my approach was junk from the begginning; those 2 answers made me notice. They apported awesome information, some of what I didn't even imagine that existed. Maybe I should try to summarize the point of the question itself... or try to improve the question some other way... – SebasSBM Aug 09 '15 at 00:18

2 Answers2

2

Perhaps something along the lines of:

drawable/white.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <stroke android:width="1dp" android:color="#000" />
    <solid android:color="#fff" />
</shape>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white1"/>
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white2"
        android:layout_toRightOf="@+id/white1"/>
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white3"
        android:layout_toRightOf="@+id/white2"/>
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white4"
        android:layout_toRightOf="@+id/white3"/>
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white5"
        android:layout_toRightOf="@+id/white4"/>
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white6"
        android:layout_toRightOf="@+id/white5"/>
    <View
        android:layout_width="30dp"
        android:layout_height="160dp"
        android:background="@drawable/white"
        android:id="@+id/white7"
        android:layout_toRightOf="@+id/white6"/>
    <View
        android:layout_width="16dp"
        android:layout_height="100dp"
        android:layout_marginLeft="-10dp"
        android:layout_marginRight="-6dp"
        android:background="#000"
        android:id="@+id/black1"
        android:layout_toRightOf="@+id/white1"/>
    <View
        android:layout_width="16dp"
        android:layout_height="100dp"
        android:layout_marginLeft="-6dp"
        android:layout_marginRight="-10dp"
        android:background="#000"
        android:id="@+id/black2"
        android:layout_toRightOf="@+id/white2"/>
    <View
        android:layout_width="16dp"
        android:layout_height="100dp"
        android:layout_marginLeft="-10dp"
        android:layout_marginRight="-6dp"
        android:background="#000"
        android:id="@+id/black3"
        android:layout_toRightOf="@+id/white4"/>
    <View
        android:layout_width="16dp"
        android:layout_height="100dp"
        android:layout_marginLeft="-8dp"
        android:layout_marginRight="-8dp"
        android:background="#000"
        android:id="@+id/black4"
        android:layout_toRightOf="@+id/white5"/>
    <View
        android:layout_width="16dp"
        android:layout_height="100dp"
        android:layout_marginLeft="-6dp"
        android:layout_marginRight="-10dp"
        android:background="#000"
        android:id="@+id/black5"
        android:layout_toRightOf="@+id/white6"/>
</RelativeLayout>

piano

Replace with View with ImageButton, if that is your preference.

tachyonflux
  • 20,103
  • 7
  • 48
  • 67
  • As long as I can catch the touch of a single key and process it from Java, I don't care if it is a View or a ImageButton. I'll test your approach and see if it fits my needs. Thanks. However, maybe in the future I'll return to ImageButton again to offer better graphics for keys. – SebasSBM Aug 08 '15 at 22:54
  • It is an outstanding layout, awesome job! After copy-pasting it, it looks perfect! After analyze the XML structure in a quick view, I understand how it works: you drawn 7 white rectangles, then 5 black rectangles. Just brilliant! Now I can start thinking on how to make Java interact with these keys... – SebasSBM Aug 08 '15 at 23:59
1

Is it possible to make the ImageButtons shown above "overlap" on purpose for making the black keys fit like they should, without depending on Java logic to achieve it?

You are welcome to use RelativeLayout. Unlike LinearLayout, RelativeLayout supports Z-axis ordering. Later children of the RelativeLayout will be higher on the Z-axis than will earlier children. So, you'd have:

<RelativeLayout>
  <ImageButton /> <!-- white key -->
  <ImageButton /> <!-- white key -->
  <ImageButton /> <!-- white key -->
  <ImageButton /> <!-- white key -->
  <ImageButton /> <!-- white key -->
  <!-- for however many white keys you have -->

  <ImageButton /> <!-- black key -->
  <ImageButton /> <!-- black key -->
  <ImageButton /> <!-- black key -->
  <!-- for however many black keys you have -->
</RelativeLayout>

If not, is there a way to customize ImageButton objects to have a shape different than rectangular?

Your image does not have to be rectangular — just use transparent pixels. However, the touch target will be rectangular. IIRC, there are third-party libraries for non-rectangular buttons.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Good point for the second question's approach. However, those pixels are already transparent. What should I do next? If I google 'IIRC', maybe I'll find some relevant documentation... – SebasSBM Aug 08 '15 at 21:34
  • On the other hand, your first approach have a unknown concept for me: what's Z-axis? It's some kind of variable that determines generation in parent-child paradigm or what? In addition, RelativeLayout would cause the screen to rotate, and that would make much more difficult to keep the integrity for this kind of button combination... or am I wrong and ignoring something about this? – SebasSBM Aug 08 '15 at 21:39
  • For the record: I'm googleling some of this stuff while asking: "Z-axis ordering" and "IIRC android libraries" – SebasSBM Aug 08 '15 at 21:42
  • @SebasSBM: In computer programming, we usually think of three positional dimensions as X, Y, and Z. In Android (and many other environments), X is horizontal across the face of the screen, Y is vertical across the face of the screen, and Z is, in effect, perpendicular to the screen, heading towards the user's eyeballs. When it comes to "overlap", that is referring to two elements that share X/Y positions; the one higher on the Z axis determines the color of the pixel (barring translucency). "RelativeLayout would cause the screen to rotate" -- um, I don't see how. – CommonsWare Aug 08 '15 at 21:44
  • @SebasSBM: "IIRC" = "if I recall correctly". This is a typical Internet abbreviation. – CommonsWare Aug 08 '15 at 21:45
  • Thank you for the clarification. So, I just have to search those libraries. If I'm lucky, maybe there's some kind of library that adapts shape based on transparent pixels. About the RelativeLayout, I just remembered while writing this: RelativeLayout is the key for gyroscopic spinning of layout, but it won't force it. I've been without developing anything with Android for a long time. Please excuse me for the mental lapsus. I shall analyze all your information calmly, make some source editions and tests and, probably, edit this question. Thanks a lot. – SebasSBM Aug 08 '15 at 22:00