i was requested to make in android a view that groups several items like checkboxes or text views in vertical rows, separated by transparent dividers while the background is with a certain alpha level and the edges are round.
I thought of two solutions and i hope for some feedback on good\bad or other solutions if you got'em.
just use regualr linear layout but have a single style A that uses a 9 patch as background, includes padding,margins and whatever i need to make it look like what i want. i then create another style A.up and A.down that represents the upper most and lower most items that will use a different 9-path with round corners.
inherit from linear layout, in the onMeasure and layoutChildren add to all the children some kind of space between them, i can create new attribute for it that can be customized in a style. i can override the dispatchDraw to paint the background for each view before it draws so i can paint my round borders, my only demand will be that each View added to this layout will have to be with transparent background.
So what do you think ?
Eventually i decided to use a List with customized divider.
It looks good, however a list got a very nasty bug when it comes down to items with states like buttons and clickable textViews,
you get no focus for the item and don't see the ornage bar
you don't seem to get the evnets flowing to the children of the View in the list.
I'm notsure how to resolve that one, i've seen numerous mails about it in the developres mailing list and here, most saying don't put statefull objects in a list.
So it mist not be the solution for me.
Nest thing i'll try is extending the normal layouts to have a bar in their bottom and use regualr linear layout with round corners drawable.
Related
How to create this below view.
1)using listview or
2)inflating custom view in scrollview.
This is not only problem.
If list view then how to overlap the rows.
Each row have different color and that will come from api webservice.
In listview, at each row i have problem with red part which i have marked in second image.
even each row background is different and that same color will appear in below row.
How to do texture effect in listview?
The issue breaks to many things:
How to draw overlapping views?
I would try setting negative values for vertical paddings, but it's a wild guess. Also, you can just divide the graphics and draw views as rectangles containing view N and some parts of the N+1th view.
What about non-rectangular hit area?
You can manually detect clicks using color picking, shapes, or just simplify the view's clickable area to a rectangle.
What about visibility detection?
ListView shows only views, which are visible. I'm not sure, but most likely it won't work with negative paddings or similar hacks.
Personally I would write a custom view with ListView-like adapter and dynamic row loading.
I have try a many ways, and the best and fastest is simple set negative divider to listview like so:
android:dividerHeight="-100dp"
I'm trying to build an Android app where I would like to display some Buttons in various places, as in the demo image attached.
The challenge here is creating the custom buttons and arranging them.
As for the custom Buttons, I guess I could achieve that using CustomViews or a simple button with a Custom Drawable as Background.
Are these the right points to start, any other ideas?
On arranging them, I have no clue how to achieve that.
As Android_Crazy and Closeratio have already said, a RelativeLayout is the most suitable option for custom placement of buttons in general. However, for the exact placement of buttons pictured in your example, a LinearLayout would work just fine.
In a LinearLayout you may place views under or above eachother (with android:orientation = "vertical", relevant for your example) or next to each other (android:orientation = "horizontal"). You can also add margin to your views to alter the horizontal position (layout_marginLeft or layout_marginRight) or the vertical position (layout_marginTop or layout_marginBottom).
As for the buttons' appearance, I always use custom background drawables, usually with a custom xml to add a different drawable for when the button is being pressed or selected.
I've modified a list view to have a different selection color and item backgrounds. Things are working perfectly until I set a custom color on the application or activity background (solid color, png, gradient). I tried using cache color hint also, but it does not seem to work.
I've been on google pretty much the whole of yesterday and haven't found an answer. The closest I've come is this thread:
The gentleman seems to say that this is as designed. If it is I'd like to hear how I could change the background color of the entire list view (I'm talking about the area in the list view that may be empty).
If you want to look at some code you will find it here.
Thanks
Manish
I'm not entirely clear on what you are asking, so let me explain how all the items that you are playing with work together, and perhaps your answer will be in there somewhere. There are three distinct visual elements that you have described in your question:
A list item's background
The list selector
The overall ListView's background
By default, they will be drawn in that hierarchy, meaning (1) is drawn on top of (2), (2) is drawn on top of (3), and so on. On a ListView with no customization, items 2 & 3 are transparent and the selector is a drawable with multiple states. Because of this, any custom colors you apply to the Activity or any View beneath the ListView is going to show through, due to the transparency.
If you look at the order in which these things are drawn, you can start to see how customizing one element may cover up any customization done to another element. For example, if you set an opaque background on each item of the list, and listSelector attribute the list has will be completely covered up (unless drawSelectorOnTop is set...which is why when developer do that they provided a drawable with states as the background item).
ListView is just another view, and you may set its background attribute directly if you wanted to provide a background to the entire ListView and hide the Views displaying underneath it. Again, if you were to set a custom list item background, this would not be visible except for areas where the ListView is large enough to display all its elements and there is extra space below them.
The job of cacheColorHint is to optimize scrolling performance by telling each list item to draw itself with a solid color background (while scrolling) instead of being transparent. If you set a solid color background on ListView or the Activity beneath, this value should be set to the same color. If your background is a gradient or image, you cannot use this optimization and it should be set to transparent (i.e. #0000)
Hope that Helps.
I am interested in creating a ListView where each row is marked the way it is done in GMail for 3.0+. This creates a nice separation of the left and right ListFragment.
Other examples include also Google Calendar on 2.3.4 for instance where a color marker is on the left of the ListView.
See the grey vertical divider between the two lists. How does one achive something like this? A bonus would be also the alternating width, but I guess that is only a smaller layout change.
I know I could probably do something like inserting an ImageView in there and then fill it with the color I would like but it seems to me that this is an ugly hack.
Another question would be also if there is a generalized way to combine the two ListView fragments somehow the way the GMail or Mail applications do it.
If you want speed, then the option I would go for is to use a custom View class (e.g. extend RelativeLayout) for the row container View and override the dispatchDraw(Canvas canvas) method.
The dispatchDraw method is called after the View has drawn its own contents and before it draws its children - the children are drawn when you call super.dispatchDraw.
Use this to do something like
private boolean mDrawMarker = false;
public void setShouldDrawMarker(boolean drawMarker) {
mDrawMarker = drawMarker;
}
public boolean getShouldDrawMarker() {
return mDrawMarker;
}
#Override
public void dispatchDraw(Canvas canvas) {
// draw the children of our view
super.dispatchDraw(canvas);
// draw our marker on top of the children if needed
if (mDrawMarker) {
// e.g. canvas.drawRect(...) or canvas.drawBitmap(...)
}
}
This way you avoid adding any extra views to the hierarchy which means you won't incur any penalty in the layout or measuring phases. Remember to re-use Paint and Rect objects if drawing a rectangle rather than creating a new one each time. Similarly if you use a bitmap you should share the same Bitmap instance across all instances of your View rather than loading a new one from your resources each time (this does not mean putting them in static fields)
For the indentation of the items, since in this case the lists don't seem to be overlapping you could (off the top of my head):
Set a left margin on the row container (not totally sure this will work)
Wrap the row container in a LinearLayout and set the left padding on this (if the above doesn't work)
Use a custom view class (if setting the left margin doesn't work)
Go with #commonsware suggestion and use two Views - one on the left with the grey background color and another to the right of that with the marker color - then just set the view on the left to visible/gone if you want indentation/no-indentation
As for the overlapping of the Views in the second example, I'll defer to #commonsware answer.
Please tell me if I have understood the problem correctly.... You would like to mark certain rows as selected, and selected rows appear to be indented visually (with a different colour and margin)?
Here are 2 techniques:
1 - Using a StateListDrawable for the row background:
If so I would create a list row layout file and set the "background" property to a StateListDrawable (can be XML). This will allow the row to switch visual states for selected and not selected.
The "drawable" attribute of the StateListDrawable would be a 9-patch PNG, one for the un-selected state that includes no margin, and one for the selected... the selected one would define a margin within the PNG itself, by specifying the content-area/bottom black line to not extend fully to the left hand side of the PNG, leaving a region which is your unscaled margin.
For the benefit of people finding this, Radley Marx just posted an excellent post on 9 patch: http://radleymarx.com/blog/simple-guide-to-9-patch/
With ListViews it's sometimes the case you want to turn off the "listSelector" (which is a separate entity either rendered above the list, or behind) and instead use the "duplicateParentState" attribute to allow the row itself to display the selection (no list selector needed). This can provide a bit more creative freedom, especially when you want to have variable-width margins on certain rows, or several types of row that all look different. Totally depends on the design though.
2 - Using a margin for each row:
If you decided you needed multiple types of colour indicator and so on, you may have to use a different approach, providing a margin attribute (which probably won't just work straight away)... This relates to how LayoutParams are used by the layout system. I'm trying to remember the exact details, but I think this is due to the different types of LayoutParam subclass, and the properties of a MarginLayoutParam (or subclass of that) e.g. marginLeft may be ignored by the layout code of the ListView. You should be using an instance of AbsListView.LayoutParams, which includes no options for margins. One way is to nest your row inside a container View (subclass) which does allow for margins in its LayoutParams*. I'm certain I didn't end up doing this extraneous-nesting but I'll have to dig into some code to remember the better solution.
You mention putting an ImageView and filling it with colour. There are a couple of alternatives you could look at... The most performant would probably be to define your own ListRow class and use onDraw() to actually draw the row contents yourself, canvas.draw_xyz() to paint the little colour tab, and draw text etc for the rest, rather than build the row in a composite layout. The second method using layouts would be to have a lighter-weight <View layout_height="match_parent" layout_width="4dip" background="#ffff0000" /> for example.
*A golden rule in Android layout: Complex UI hierarchy is death to performance, especially with things like ListView. It's often possible to avoid this by using other things: RelativeLayout, drawableTop(etc), 9-patch images, rather than adding more Views.
If I have misunderstood and the above is just too basic please could you provide some more detail, maybe a diagram indicating the exact part you need to reproduce.
How does one achive something like this?
Off the cuff, I'd use a View with the desired background color, visible when you want it, invisible when you don't.
A bonus would be also the alternating width, but I guess that is only a smaller layout change.
I do not know what you mean by "alternating width". I think there are two Views with the desired background color in a horizontal LinearLayout, with only one visible.
I know I could probably do something like inserting an ImageView in there and then fill it with the color I would like but it seems to me that this is an ugly hack.
Well, ImageView is a bit heavier than is needed. Otherwise, I fail to see why this is a hack. Think of them as icons that simply happen to be tall, thin, gray, and not always needed.
Another question would be also if there is a generalized way to combine the two ListView fragments somehow the way the GMail or Mail applications do it.
Use a RelativeLayout, so the right-hand fragment can float over the left-hand fragment.
I have ListView. I would like to fill each row of ListView with a background from left to x% ...
So what I want is:
Item - 50% of background is colored
Item - 20% of background is colored
Item - 90% of background is colored
Is it possible to this?
Thanks for the answer!
As far as I know this is not possible out of the box. But I think you can archive is with a little trick.
You have to define a custom view for you rows. This view has a RelativeLayout as root element on which you can set the background color you want to have.
You then add another view element to the root element which covers a part of the root element. The background color of this element should be set to black and should be aligned to the right. The RelativeLayout provides many attributed you can use to arrange the elements.
Furthermore you have to write a custom adapter which handles the creation of the single list items views. When you override the getView() method where the view elements for each single row are created and inflated to the ListView, you calculate and set the width of the "cover"-element in such a ways that it covers a part of the root element.
The difficult part will be to calculate the width of the cover-element so that the rest of the root element which is not covered and still visible correspond to the percentage you want it to have.
Here you find a short tutorial about how to implement a custom Adapter with a custom view for the list items.
It is possible by the concept of custom layouts. This is a good article for to learn more. Also, I think you need to go through the NotePad tutorial in Android official site.