I have a ListView in one of my activity. I have one customview which is created extending ImageView.I want to add this customview as background of listview.As we have two functions setBackGroundDrawable(Drawable d) and setBackGroundResource(resource).I cant use any one of this ?Anyone having any good idea how i can do this? I searched but could not get any solution.
Edited : As I got a tutorial
When you want to dynamically draw some two-dimensional graphics, a ShapeDrawable object will probably suit your needs. With a ShapeDrawable, you can programmatically draw primitive shapes and style them in any way imaginable.
A ShapeDrawable is an extension of Drawable, so you can use one where ever a Drawable is expected — perhaps for the background of a View, set with setBackgroundDrawable(). Of course, you can also draw your shape as its own custom View, to be added to your layout however you please. Because the ShapeDrawable has its own draw() method, you can create a subclass of View that draws the ShapeDrawable during the View.onDraw() method. Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a View:
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
In the constructor, a ShapeDrawable is defines as an OvalShape. It's then given a color and the bounds of the shape are set. If you do not set the bounds, then the shape will not be drawn, whereas if you don't set the color, it will default to black.
With the custom View defined, it can be drawn any way you like. With the sample above, we can draw the shape programmatically in an Activity:
CustomDrawableView mCustomDrawableView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCustomDrawableView = new CustomDrawableView(this);
setContentView(mCustomDrawableView);
}
If you'd like to draw this custom drawable from the XML layout instead of from the Activity, then the CustomDrawable class must override the View(Context, AttributeSet) constructor, which is called when instantiating a View via inflation from XML. Then add a CustomDrawable element to the XML, like so:
<com.example.shapedrawable.CustomDrawableView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
The ShapeDrawable class (like many other Drawable types in the android.graphics.drawable package) allows you to define various properties of the drawable with public methods. Some properties you might want to adjust include alpha transparency, color filter, dither, opacity and color.
You can also define primitive drawable shapes using XML. For more information, see the section about Shape Drawables in the Drawable Resources document.
Try it :
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.shapedrawable.CustomDrawableView
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"/>
</RelativeLayout>
And set your custom draw-ables to ImageView.
Hope this will work. :)
You cannot use your custom View as Background of ListView.
However a workaround could be:
Use RelativeLayout as parent layout container.
Add a LinearLayout with property of fill_parent for both width and
height
Give any id as list_background to the LinearLayout.
Then add the ListView to the parent RelativeLayout.
Add property android:layout_centerInParent="true" to both of the
ListView and LinearLayout
Remove background of the ListView and your CustomRow if you have
any.
Now get the LinearLayout in Java and add the View to that
LinearLayout
Related
I'm having a requirement of draw a border around a parent layout in Xamarin.Android it can be any layout like FrameLayout, LinearLayout etc.
I have achieved this by using GradientDrawable - Which is just like setting a background for the layout with a shape.
So my requirement will be achieved
Query
When setting corner radius for the border, it is not clipping the children. How to clip the children or any other way alternative to do the both? Kindly share your suggestion on this.?
Note: I have tried with ClipChildren, ClipToPadding for the layout.
PS: Above images are mentioned for illustration purpose, they are not the exact output.
TIA.
You can clip the view using canvas. Use ClipPath(path) method of Canvas to clip the required area.
Syntax:
Path path = new Path();
path.AddCircle(200,200,100,Direction.CW);
canvas.ClipPath(path);
You can make use of ViewOutlineProvider API. As an example usage see ClippingBasic project.
Having defined outline provider class as such:
private class OvalOutlineProvider extends ViewOutlineProvider {
#Override
public void getOutline(View view, Outline outline) {
outline.setOval(0, 0, view.getWidth(), view.getHeight());
}
}
Then apply view outline to parent:
View parent = findViewById(R.id.parent);
parent.setOutlineProvider(new OvalOutlineProvider());
parent.setClipToOutline(true);
ViewOutlineProvider is accessible starting from API 21. Not sure, whether the solution is applicable for Xamarin (hope it does).
Setting ClipToOutline = true; for the parent, resolves the issue.
I am trying to design an UI very similar to this. I have been able to design it almost similar to the image above, but am not getting a way to implement the slanting or sloping part.
1) Can any one give an example layout of how can I implement the slanting layout?
2) And how can I place the FAB right there over the slant portion?
Any help would be really appreciated.
You can create a custom view with Slant top using Canvas and then place it over your TextView, to achieve this look and feel.
Code snippet for slant top custom view:
public class SlantView extends View {
private Context mContext;
Paint paint ;
Path path;
public SlantView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
mContext = ctx;
setWillNotDraw(false);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
#Override
protected void onDraw(Canvas canvas) {
int w = getWidth(), h = getHeight();
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(0,0);
path.lineTo(0,h);
path.lineTo(w,h);
path.close();
canvas.drawPath(path, paint);
}
}
Code snippet for how to use it with TextView
<com.pix.app.views.SlantView
android:layout_width="match_parent"
android:layout_height="30dp"
android:id="#+id/slant_view"
/>
<TextView/>
Other way to achieve Slant View is this:
<FrameLayout android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#color/colorAccent"
xmlns:android="http://schemas.android.com/apk/res/android" >
<ImageView
android:layout_width="match_parent"
android:layout_height="280dp"
android:src="#color/colorPrimary"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:rotation="-70"
android:layout_marginTop="100dp"
android:background="#color/colorAccent"></LinearLayout>
</FrameLayout>
This will give you following output:
1) Can any one give an example layout of how can I implement the slanting layout?
You cannot. Views are always rectangular. You may however make it look slanted, i.e. with background image.
2) And how can I place the FAB right there over the slant portion?
You cannot have slant. It's just bottom edge of the square bounding box. So you should be able to put it there w/o any problem.
Normally images are represented in rectangular form. You can use padding/margin to design UI according to your need. Obviously other than sloping part will be transparent image.
You need to have the root or at least the immediate parent layout as FrameLayout, then,
1) For the image part, you can have a normal ImageView to show the image. Below that you can have a LinearLayout (blank, with white background).
Now just tilt the blank LinearLayout to an angle probably 45 degrees to cut the background image in slant style. Here, just set the XML property of the blank LinearLayout,
android:rotation = "45"
2) For the FAB, just move it to the cutting point, gravity of the layout should be set to right according to your screenshot.
Hope this helps. Cheers!
You'll have to write a custom View to do it. There's no native control that can do this.
Canvas's provide support for clipping paths, so it's easy enough to clip the image provided you can draw the image. That being said, drawing large images in an OnDraw implementation is less than straightforward (memory management and correct scaling and caching behaviour isn't difficult, but it's less than trivial)
An easier way to do it would be to extend something like a FrameLayout or some kind of ViewGroup. If you override dispatchDraw, you can push a clip path onto the canvas, which will clip children. And then you can put other controls inside your custom control.
Something like this:
public class ClipFrameLayout extends FrameLayout {
.... constructors and stuff...
#Override
void dispatchDraw(Canvas canvas)
{
canvas.save();
canvas.clipPath(mCustomClipPath);
super.dispatchDraw(canvas);
canvas.restore();
}
}
I wanted to implement a custom view which is combined by a ImageView and a TextView like this.
A class called IconTextView is created by extending TextView, and the onDraw function was rewrittend by this.
#Override
protected void onDraw(Canvas canvas)
{
if (bitmap != null)
{
//something are done before
canvas.drawBitmap(bitmap, src, target, getPaint());
canvas.translate(target.right + 2, 0);
}
super.onDraw(canvas);
}
Then a IconTextView was added into the main layout like this.
<com.liujilong.carson.icontextview.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
mobile:iconSrc="#drawable/ic_launcher"
android:text="myIconTextView"
android:textSize="30sp"
/>
The IconTextView shown in my phone like this.
Sorry that i can not post picture.
The problem is that the width of the View was still the width of the TextView, and I translated the canvas. So the text could not show totally.
How can I change the width of the IconTextView?
I don't think you should have to do anything as drastic as override onDraw.
You could just have a horizontal LinearLayout that has an ImageView and a TextView
Even simpler, you can set the left drawable of the TextView using the the attribute android:drawableLeft="#drawable/my_icon". If you have to change it in code, the corresponding method is TextView.setCompoundDrawablesWithIntrinsicBounds(int,int,int,int). The images would have to be set up as drawable resources for this to work.
Is there something special about your custom view that these ideas won't work?
Now I need to implement a function just like the html tag , see the pic below:
Firstly, I set the drawableLeft, and it show like this:
It's not my suppose do. After that I create a class 'LiTextView' implements TextView, and override the onDraw() method like this:
#Override
protected void onDraw(Canvas canvas) {
Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
Drawable drawableLeft = drawables[0];
if (drawableLeft != null) {
canvas.save();
canvas.translate(10, 50);
drawableLeft.draw(canvas);
canvas.restore();
}
}
super.onDraw(canvas);
}
the xml file like this:
<me.naiyu.android.textviewlidemo.widget.LiTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:drawableLeft="#drawable/circle_dot"
android:drawablePadding="10dp"
android:textColor="#000000"
android:textSize="18sp"
android:text="Displays text to the user and optionally allows them to edit it. A TextView is a complete text editor, however the basic class is configured to not allow editing"/>
and it became this(have two circle):
How can I implement the picture one, I now have no idear!
The reason why the "dot" is drawn twice is because you call super.onDraw(canvas). You've drawn the dot yourself in the top-position, and then you let the system draw the dot on the original position by calling the super.
Unfortunately, you have to call super.onDraw(canvas) in order to draw the text. A better approach to achieve what you want is by creating a custom Drawable that wraps the Drawable you want to display, and then override the draw(Canvas) method of the custom Drawable.
See my answer here for an example. The only downside is that you have to set the drawableLeft from code, not XML.
Is it possible to add TextView and ImageView on canvas?
Canvas does not inherit from ViewGroup, so it does not have the ability to add child views to it.
With Canvas, you use drawBitmap and drawText methods to draw images and text instead of adding child controls like TextView and ImageView.
It's a round about way, but this tutorial adds a textview to his canvas:
http://www.helloandroid.com/tutorials/how-draw-multiline-text-canvas-easily
If you need to freely position ImageViews and TextViews, you should use a RelativeLayout.
The RelativeLayout has advanced positioning features and allows overlapping.
- put your view (which is using canvas) inside the RelativeLayout,
public class YourComponent extends View{
#Override
protected void onDraw(Canvas canvas)
...
public void onDraw(){
....
....
ImageView yourImageView = .....
RelativeLayout.LayoutParams fParams = new RelativeLayout.LayoutParams(25,25);
fParams.leftMargin = 100; //x coordinate
fParams.topMargin = 25; /y coordinate
yourImageView.setLayoutParams(fParams);
((RelativeLayout) YourComponent.this.getParent()).addView(yourImageView);
}
}
above code : i created layout params which shows 25x25 dimensions for view. and after that , i used margins to set proper position on the parent layout. and set this LayoutParams to ImageView. and for last, i added this imageView to parent Layout.
But beware that during the onDraw() execution, calling operation on external view may stop onDraw(). so if you want to use this way be sure you already completed all onDraw operation.
I am not so sure why this happens. I did not try to observe too much on it yet.