How to create a 1px border grid - android

I would like to create a clean grid.
I already have something that work, but I have a 2px border.
Here is my code :
In an activity :
setContentView(R.layout.activity_game);
GridView gridview = (GridView) findViewById(R.id.gvGame);
ButtonAdapter buttonAdapter = new ButtonAdapter(GameActivity.this, myList.getList());
gridview.setAdapter(buttonAdapter);
activity_game.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<GridView
android:id="#+id/gvGame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#android:color/white"
android:gravity="center_vertical"
android:numColumns="3"
android:scrollbarStyle="outsideOverlay"
android:stretchMode="columnWidth" />
</RelativeLayout>
Somewhere in ButtonAdapter :
button.setBackgroundResource(R.drawable.grid_button);
grid_button.xml (drawable) :
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#android:color/black" />
</shape>
</item>
<item
android:bottom="1px"
android:left="1px"
android:right="1px"
android:top="1px">
<shape android:shape="rectangle">
<solid android:color="#android:color/white" />
</shape>
</item>
</layer-list>
Result :
How can I get a 1px bordered grid everywhere ?
Note: each square must be clickable.

How about giving a 1px border on your RelativeLayout's top and left side and 1px border on each cell's right and bottom side?
This will make the effect you want, but not sure what you want the result to be if the number of cells in the last row is less.

I'd suggest to use the spacing attributes of the GridView instead to achieve uniformly spaced grid.
<GridView
...
android:horizontalSpacing="1px"
android:verticalSpacing="1px"
... />
This creates a space between the GridView's items with the size of 1px.
If you want the spacing to be black, you have to set the GridView's (or its parent's) background to black.
Of course now you have to remove the black border of your button's background.

Related

How to put a horizontal divisor line with depth on the top side

I'm making an activity to my app, and I have to divide some sections of my window with a line. I would like to do something like this:
I only tried with android:elevation="2dp on View in XML layout:
<View
android:layout_width="fill_parent"
android:layout_height="12dip"
android:layout_marginTop="15dp"
android:background="#E0E0E0"
android:elevation="2dp"
/>
But this only put depth on the bottom.
Higher elevation values will also add some shadow at the top of your View.
If you want more "shadow" at the top you can mimic it using a custom XML Drawable with white background and a top border of grey color and really small size (it can also be a gradient if you don't like the solid line):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Background -->
<item>
<shape android:shape="rectangle">
<solid android:color="#android:color/white" />
</shape>
</item>
<!-- Top "line" -->
<item android:gravity="top">
<shape android:shape="rectangle">
<size android:height="1dp" />
<solid android:color="#ccc"/>
</shape>
</item>
</layer-list>
If it's a ViewGroup you can also add a View with a small height value aligned right to its top with a grey background or gradient. It's simpler, but also a bit dirtier and worse for layout performance.

How to round corners of list item at the top and bottom of the list view? (not only for top and bottom items)

I have a listview with rounded corner at the top and the bottom. Look like this image:
But when I click on the top and the bottom of ListView, the List Item's background is rectangle not rounded as background of ListView at top and bottom. Like this image :
How to resolve this issue?
this is my code :
1/ list_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cacaca">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/list_border"
android:listSelector="#drawable/list_selector"/>
</LinearLayout>
2/ list_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff"/>
<corners android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
</shape>
3/ list_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#color/colorPrimary" />
</selector>
4/ ListActivity.java
ListView listView = (ListView)findViewById(R.id.listView3);
ArrayList<String> listItems = new ArrayList<>();
for(int i=0;i<20;i++){
listItems.add(""+i);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_selectable_list_item, listItems);
listView.setAdapter(adapter);
This solution is not pretty but it does what you want. The idea is to invert the corner and draw them as foreground :
the ListView is wrapped in a FrameLayout :
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_margin="10dp"
android:foreground="#drawable/inverted_corners"
android:layout_weight="1">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:listSelector="#drawable/list_selector" />
</FrameLayout>
which foreground (drawable/inverted_corners.xml) is set to a rounded hole, drawn with the background color. The trick is to draw a line outside the shape, instead of a filled shape :
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-11dp"
android:left="-11dp"
android:right="-11dp"
android:top="-11dp">
<shape android:shape="rectangle">
<stroke
android:width="10dp"
android:color="#cacaca" />
<corners android:radius="22dp" />
</shape>
</item>
</layer-list>
This garanties that the rounded corners are on top of the selector, and the overscroll effect.
I suggest you should set the layout with corners to your ListView's first and last element, but not to the whole ListView.
You can create two extra .xml files in addition to your list_selector.xml: one for first element with the round corners at the top (lets call it list_selector_top.xml) and another one for the last element with the round corners at the bottom (list_selector_bottom.xml).
Then you can create your own MyAdapter extends ArrayAdapter and somewhere in getView() method set the appropriate background to your element's View (if position==0 set list_selector_top.xml, if position==getCount()-1 set list_selector_bottom.xml, by default set list_selector.xml).
It might be not the simpliest approach, but it works.
Set your corner radius to list view selector also using this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/list"
android:state_pressed="true"
>
<shape>
<solid android:color="#color/colorPrimary"/>
<corners
android:radius="10dp"/>
</shape>
</item>
</selector>
so your selection will not be cross boundry of list view.
cons - you will not able to define which radius you have to set as per top and bottom part that is why have to set radius to all sides.
hope this should help or at least give you some direction to resolve your issue.
If you can use FrameLayout as parent to the ListView, then set the cornered shape as foreground to the parent FrameLayout.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="#drawable/list_border">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:listSelector="#drawable/list_selector"/>
</FrameLayout>
If you want to use LinearLayout as parent of ListView, then surround your ListView with ForegroundLinearLayout and set the cornered shape as foreground to the ForegroundLinearLayout.
What is ForegroundLinearLayout? It is LinearLayout with Foreground property like FrameLayout. Get the code from Chris Banes. https://gist.github.com/chrisbanes/9091754
Your code should be:
<?xml version="1.0" encoding="utf-8"?>
<ForegroundLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foreground="#drawable/list_border">
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:listSelector="#drawable/list_selector"/>
</ForegroundLinearLayout>
please add padding in your style.i updated style here.
2 list_border.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff"/>
<corners android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<padding android:left="10dp"
android:right="10dp"
android:top="10dp"
android:bottom="10dp"
/>
</shape>
This can be done easily by using Android's support library's CardView. Just wrap your ListView in a CardView layout and set a cardCornerRadius to the CardView, like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#cacaca">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
card_view:cardCornerRadius="10dp"
>
<ListView
android:id="#+id/listView3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:listSelector="#drawable/list_selector"/>
</android.support.v7.widget.CardView>
</LinearLayout>
Dont forgot to import the CardView's support library:
compile 'com.android.support:cardview-v7:23.1.1'

Set listView divider's width

I'm trying to use a listView with a divider and I was about to change divider's width so I looked in the web site and I found this solution :
Listview divider margin
When I tested in my app, I have no divider, but if I switch to use a simple color the divider appears again
This this my code :
my Activity layout :
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="80sp"
android:elegantTextHeight="true"
android:text="Paramètres"
android:textSize="24sp"
android:gravity="center"
android:textColor="#ffffff"
android:background="#191919"/>
<ListView
android:id="#+id/list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:dividerHeight="2dp"
android:divider="#drawable/list_divider">
</ListView>
</LinearLayout>
list_divider.xml
<?xml version="1.0" encoding="UTF-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="15dp"
android:insetRight="15dp" >
<shape
android:shape="rectangle" >
<stroke
android:dashGap="1dp"
android:dashWidth="1.5dip"
android:width="2dp"
android:color="#000000" />
<size android:height="3dp"/>
</shape>
</inset>
You are giving wrong file name to your divider attribute.Change this line
android:divider="#drawable/list_devider"
To
android:divider="#drawable/list_divider"
because your list divider drawable file name is list_divider not list_devider
And I will suggest you to use px as a dividerHeight instead of dp
if you specify 1dp or 1dip, Android will scale that down. On a 120dpi device, that becomes something like 0.75px translated, which rounds to 0. On some devices, that translates to 2-3 pixels, and it usually looks ugly or sloppy
For dividers, 1px is the correct height if you want a 1 pixel divider and is one of the exceptions for the "everything should be dip" rule. It'll be 1 pixel on all screens. Plus, 1px usually looks better on hdpi and above screens
So I modified my listdivide.xml file to that, the it work :
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="16dp"
android:insetRight="16dp">
<shape>
<solid android:color="#000000" />
<corners android:radius="1dp" />
</shape>
</inset>
But i still don't know why the first dosn't work :)

android:shape="line" not visible

I have the following drawable shape:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line" >
<stroke
android:width="1dp"
android:color="#e0e0e0" />
</shape>
And use this with this image:
<ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="8dp"
android:src="#drawable/line" />
When I set android:layout_height to 1dp, the shape is not visible. If the android:layout_height is set to 2dp, the shape is visible.
Why do I have to use a height of 2dp?
Ralph
It's a stroke, so it goes around the shape. Meaning it passes the line on both sides, so it will need twice the width of the stroke.
You could just set <size> tag in your shape and put that on 1dp and <solid android:color=""> for the color

Possible to create a fixed-width drawable in XML?

I'm trying to simplify some graphics from requiring a 9-patch for each density, to just using an XML drawable. It's a fairly simple graphic:
2 Segments:
8dp wide for both segments
Top segment is 2dp tall
Bottom segment fills the view
Right side is filled with transparency
Giving this result when set as a background image:
It seems like this should be fairly simple to recreate as an XML drawable, and would avoid creating 5 different 9-patch graphics. However, I've looked into layer-list drawables, inset drawables, clip drawables -- they all seem to require that you know the size of the view beforehand (e.g. to keep it 2dp for an inset, you'd need to set insetRight to the width of the view - 2dp). I also tried using the shape tag's size tag, but that doesn't keep a fixed size, just a fixed proportion (so for taller views it will scale proportionally).
Am I overlooking something simple, or is this something I'd have to resort to checking programatically after layout?
This is not possible. This is the best solution I found. Only xml, no coding, no bitmaps, no additional views )
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#ff0000" />
</shape>
</item>
<item
android:top="4dp">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#00ff00" />
</shape>
</item>
<item
android:left="10dp">
<shape
android:shape="rectangle">
<solid
android:color="#FFFFFF" />
</shape>
</item>
</layer-list>
Via code you can make your own drawble type with desired behavior. Xml drawable very limited. IMHO my suggestion is the closest to what you demanded.
I think the answer by #Leonidos is very close to what I'm proposing, except I'm using the drawable as a separate view instead of the background for the entire list detail layout. This allows it to be a fixed width and to let the item text have its own background. Let me know if I'm not understanding your constraints.
The following file is "res/drawable/list_left_border"
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<solid android:color="#e76e63" />
</shape>
</item>
<item android:top="2dp">
<shape android:shape="rectangle" >
<solid android:color="#ffc257" />
</shape>
</item>
</layer-list>
Then on the layout for the list item in "res/layout/list_item.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"
tools:context=".MainActivity" >
<View
android:background="#drawable/list_left_border"
android:layout_width="8dp"
android:layout_height="match_parent" />
<TextView
android:id="#+id/listItemText"
android:textSize="15sp"
android:padding="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Here's the image. The background is pink to show that the list item is transparent.
I'm going to go one further and suggest a slight reworking of AndroidGuy's answer, which itself includes Leonidos' answer.
Same drawable XML, different list item XML as follows:
<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"
tools:context=".MainActivity" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="100sp">
<ImageView
android:layout_width="8dp"
android:layout_height="match_parent"
android:src="#drawable/list_left_border" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="Item Text"
android:textSize="22sp" >
</TextView>
</FrameLayout>
The FrameLayout gives the original background behaviour, rather than separation into a new view.
I've shown this below, with backgrounds to demonstrate:
This doesn't really deserve the points though.

Categories

Resources