I have ListView with ImageView in rows.
I need to draw lines between these ImageViews.
So one line is started at first row at ImageView position and ends at second row at ImageView position. And so on.
What is the best way to draw these lines?
Thank you.
UPDATE. I am sorry, I can't upload image and I speak english not very well.
It is not horizontal divider between rows. If to simplify it: line starts at vertical center of one row at ImageView position and ends with vertical center of next row at ImageView position.
I think I should try:
To override row view.
At Adapter's GetView where I create row view pass to this row view coordinates of adjacent rows.
In view's onDraw method calculate coordinates and draw line.
To override ListView. In it's OnDraw method try to get ImageView's positions and draw all lines.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView
android:id="#+id/android:list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="#FFCC00"
android:dividerHeight="4px"/>
</LinearLayout>
Have a listview seperator.
I am not sure if I understood your question correctly, but this should make really nice gradient lines between rows :
mListView = getListView();
mAdapter = new ServersListAdapter(this, new String[] {},
new String[] {}, new String[] {});
int[] colors = { Color.parseColor("#D3D3D3"), Color.parseColor("#D3D3D3"), Color.parseColor("#D3D3D3") };
mListView.setDivider(new GradientDrawable(Orientation.RIGHT_LEFT, colors));
This is an example of a view you can draw a line in. Create this class, refresh your palette if you need to.
public class LineTextView extends AppCompatTextView {
private Paint paint = new Paint();
public LineTextView(Context context) {
super(context);
}
public LineTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LineTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.parseColor("#000000"));
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(0, 0, 0, getHeight(), paint);
}
}
Now you can use it in your layout
<LinearLayout
android:layout_width="2dp"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.taskmodel.view.LineTextView
android:id="#+id/lineTextViewTopHalf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:visibility="invisible"/>
<com.example.taskmodel.view.LineTextView
android:id="#+id/lineTextViewBottomHalf"
android:layout_width="2dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
Related
I have an ImageView and I would like to draw dinamically another images on my base ImageView.
In this image for example I have a tree and I would like to draw image of people
Any suggestions to start?
yes my problem is like #Tsunaze say:
I have a tree, and I want to put heads on it,
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" >
<ImageView
android:id="#+id/iv_tree"
android:scaleType="fitXY"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:adjustViewBounds="true"
android:src="#drawable/my_tree" />
</RelativeLayout>
MyView.java :
public MyView extends View{
private Bitmap head_1, head_2;
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public MyView(Context context) {
super(context);
this.context = context;
init();
}
private void init(){
head_1= BitmapFactory.decodeResource(context.getResources(),
R.drawable.head_1);
head_2= BitmapFactory.decodeResource(context.getResources(),
R.drawable.head_2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(head_1, coordinateX_head_1, coordinateY_head_1, null);
canvas.drawBitmap(head_2, coordinateX_head_2, coordinateY_head_2, null);
}
}
You choose the coordinate you want, you can even use function like canvas.getWidth() or canvas.getHeight(). Pose yourself as a painter. Good luck.
What you have to do is create a class that extends from ImageView, set the default parameters that you want as usual and override the on draw method, this method will give you the chance to get a reference to the canvas and draw bitmaps or pretty much anything you want, but remember to call first super.onDraw to keep your default configuration and overlay your new images.
There's plenty of tutorials on how to use canvas, so now you have the proper path to take, hope this helps.
Regards
setBackgroundResource to ImageView and use setImageResource over it.
Ex :
imageView.setBackgroundResource(R.id.backgroundTree);
imageView.setImageResource(R.id.allPeople);
EDIT :
If you want multiple images to be overlayed, check this example.
You can also use RelativeLayout and add ImageView inside it programmatically.
<RelativeLayout>
<ImageView/>
<ImageView/>
<ImageView/>
<ImageView/>
</RelativeLayout>
I have a custom Relative Layout(a class extended to RelativeLayout). I draw some bitmaps on a canvas using the method dispatchDraw(). And I want to show an Edit text box on top this canvas. So I create a new instance of EditText and bring it to front. EditText adds to the layout but doesn't come to front. When I remove canvas drawing code the edit text appears.
Help me if you know a way to bring the EditText to the front of the canvas.
public class EditCardLayout extends RelativeLayout {
public EditCardLayout (Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
editText = new EditText(context);
editText.setText("My Text");
addView( editText );
editText.bringToFront();
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
// some bitmaps are drawn here...
}
}
XML :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#eceadb"
android:gravity="center">
<editCard.EditCardLayout
android:id="#+id/cardEditView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true" />
</RelativeLayout>
What order are you adding the elements in? According to the docs, the z-order is affected by the order in which the elements are drawn, with the last thing drawn on top. Try adding the edittext last.
I am playing with layouts and views in Android. My layout looks like:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.mycode.MyView
android:id="#+id/MyView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<LinearLayout
android:id="#+id/leftpane"
android:layout_width="55dp"
android:layout_height="wrap_content"
android:layout_weight="0.95"
android:background="#color/leftpane_background"
android:gravity="center"
android:orientation="vertical"
android:scrollbarStyle="insideOverlay" >
</LinearLayout>
</LinearLayout>
If i comment the lines <com.mycode.MyView .... />, the left linear layout (with id leftpane) is showed, otherwise not. If i add another layout after the leftpane layout (for example a scroll view layout), it does not get showed as well.
Why using my custom view (MyView) makes disappear all other layouts?
What i would like to do is to have my custom View for the background of the application, where i would show images, and some other view over the background, like scroll views, buttons and so on.
This is the code of MyView class. Keep in mind that i need to draw on the background of the activity an images (on the whole background, obviously not including the action bar):
/**
*/
class MyView extends View
{
TextPaint text_paint;
Paint paint;
private void InitView()
{
text_paint = new TextPaint( Paint.ANTI_ALIAS_FLAG );
text_paint.setColor( Color.BLACK );
paint = new Paint();
}
public MyView(Context context)
{
super(context);
InitView();
}
public MyView(Context context, AttributeSet attrs)
{
super(context, attrs);
InitView();
}
public MyView(Context context, AttributeSet attrs, int defaultStyle)
{
super(context, attrs, defaultStyle);
InitView();
}
#Override
protected void onDraw( Canvas canvas )
{
super.onDraw(canvas);
//int w, h;
//w = canvas.getWidth();
//h = canvas.getHeight();
//paint.setColor( Color.WHITE );
//canvas.drawRect(0, 0, w-1, h-1, paint );
//canvas.drawText( "ciao", 100, 100, text_paint);
}
};
Try to change your view's height as:
android:layout_height="wrap_content"
Maybe you did some error work when you overrode the onMeasure method in your custom MyView,
and so the MyView's match all the parent view.
Can you show your code which in the onLayout and onMeasure method of the MyView.
I have a vertical LinearLayout with two TextView inside it. The former contains a static text property (it's text never change) and the last contains a regressive timer. The image below shows both items:
I want to eliminate the blank space that both texts have both top and bottom. I've tried several approaches...
android:includeFontPadding="false"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
...but none of them removed the space above the text. How can I make both texts close to each other without any extra space?
PS: I've found this similar question, but no one answered it.
Full layout code:
<LinearLayout
android:id="#+id/boxTime"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp" >
<TextView
android:id="#+id/textRemainingTime2"
android:layout_width="wrap_content"
android:layout_heigh="wrap_content"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:textSize="70sp"
android:includeFontPadding="false"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:text="#string/title" />
<TextView
android:id="#+id/textRemainingTime"
android:layout_width="wrap_content"
android:layout_heigh="wrap_content"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:includeFontPadding="false"
android:lineSpacingMultiplier="1"
android:lineSpacingExtra="0dp"
android:paddingTop="0dp"
android:paddingBottom="0dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="0dp"
android:textSize="107sp"
android:text="#string/timer" />
</LinearLayout>
Try using negative margins. It may take a bit of playing with the numbers to get it right, but I've done it before and it worked out well.
android:layout_marginTop="-5dp"
By default, a TextView includes some padding to leave space for accent characters. You can turn that off with:
android:includeFontPadding="false"
or
textView.setIncludeFontPadding(false)
Make baseline of the text equal to the bottom of the TextView.
public class BaselineTextView extends TextView {
public BaselineTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
int yOffset = getHeight() - getBaseline();
canvas.translate(0, yOffset);
super.onDraw(canvas);
}
}
NOTE: To avoid chopping off descenders call setClipChildren(false) on your TextView's parent ViewGroup (android:clipChildren="false" in XML).
If you set includeFontPadding to false it helps.
android:includeFontPadding="false"
but if you know you don't have any descenders because you set
android:textAllCaps="true"
or you know there are no characters which have descender, you can make a custom TextView and set the height to the baseline.
public class ExTextView extends TextView {
public ExTextView(Context context) {
this(context, null);
}
public ExTextView(Context context, #Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public ExTextView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ExTextView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onDraw(Canvas canvas) {
setHeight(getBaseline()); // <--- Shrink size to baseline
super.onDraw(canvas);
}
}
The source code is included in my UiComponents test app.
https://github.com/landenlabs/UiComponents
Just use below, nothing else required.
android:includeFontPadding="false"
if you want some variations in line gap then use :
android:lineSpacingExtra
negative margins will do the trick
Since my requirement is override the existing textView get from findViewById(getResources().getIdentifier("xxx", "id", "android"));, so I can't simply try onDraw() of other answer.
But I just figure out the correct steps to fixed my problem, here is the final result from Layout Inspector:
Since what I wanted is merely remove the top spaces, so I don't have to choose other font to remove bottom spaces.
Here is the critical code to fixed it:
Typeface mfont = Typeface.createFromAsset(getResources().getAssets(), "fonts/myCustomFont.otf");
myTextView.setTypeface(mfont);
myTextView.setPadding(0, 0, 0, 0);
myTextView.setIncludeFontPadding(false);
The first key is set custom font "fonts/myCustomFont.otf" which has the space on bottom but not on the top, you can easily figure out this by open otf file and click any font in android Studio:
As you can see, the cursor on the bottom has extra spacing but not on the top, so it fixed my problem.
The second key is you can't simply skip any of the code, otherwise it might not works. That's the reason you can found some people comment that an answer is working and some other people comment that it's not working.
Let's illustrated what will happen if I remove one of them.
Without setTypeface(mfont);:
Without setPadding(0, 0, 0, 0);:
Without setIncludeFontPadding(false);:
Without 3 of them (i.e. the original):
Negative Margins would do the work. You can set it by two methods -
1) by xml - set the android:Layout_marginTop="-10dp" field negative
2) by java (Programmatically) - set the topMargin field of LayoutParams to negative.
you should change the height of TextView and maybe change android:gravity="bottom"
height is between textsize and size of textView with Wrapcontent.
public class MyTextViewBounder extends TextView {
public MyTextViewBounder(Context context) {
super(context);
}
public MyTextViewBounder(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextViewBounder(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//test kích thước thực tế với kích thước của Textview bao quanh text của nó như thế nào
int width, height;
Paint iPaint;
Rect iRect = new Rect();
iPaint = new Paint();
iPaint.setTextSize(13);
iPaint.setTextAlign(Paint.Align.CENTER);
//call below code outsite
//this.setText("Hung");
//this.setTextSize(TypedValue.COMPLEX_UNIT_PX,13);
//this..setIncludeFontPadding(false); //height from 18px down to 15px
iPaint.getTextBounds("Hung",0,4,iRect); //width = 34px, height = 12px
width = this.getWidth(); //= 30px
height = this.getHeight(); //= 18px
width = this.getMeasuredWidth(); //=30px
height = this.getMeasuredHeight(); //= 18px
width = iRect.width(); //34px
height = iRect.height(); //12 px
}
}
I have one image view (assigned one bitmap to it) and another bitmap (Transparent) for painting. How it is possible to scroll this bitmap and background bitmap at the same time to be painted at different places.
From what I understood you are trying to draw on top of a image. If thats the case, create a custom view and get the image using BitmapFactory. After you get a bitmap object, use its copy method and use that copy for the canvas of the view.
Now you can override the onDraw method of a custom view and draw anything on top of it.
This view can be added to the layout, and scrolling will happen to the view.
Edit: Sample Code
Ok this is some code that might help you. I dont have the time to go through all your code.
But I tried to understand your requirement.
I am showing the code for an activity, its xml and custom view
Activity.java
public class DrawDemo extends Activity {
private FrameLayout container;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_demo_layout);
container = (FrameLayout)findViewById(R.id.sc);
container.addView(new DrawView(this));
}
public void drawHandler(View target){
container.addView(new DrawView(this));
}
public void clearHandler(View target){
if(container.getChildCount() != 1){
container.removeViewAt(container.getChildCount()-1);
}
}
}
draw_demo_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<FrameLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="0dip"
android:id="#+id/sc" android:scrollbars="horizontal"
android:layout_weight="1.0">
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/chips"/>
</FrameLayout>
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Draw"
android:onClick="drawHandler"/>
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Clear"
android:onClick="clearHandler"/>
</LinearLayout>
DrawView.java
public class DrawView extends View {
public DrawView(Context context) {
super(context);
setLayoutParams(new LayoutParams(LinearLayout.LayoutParams.FILL_PARENT
,LinearLayout.LayoutParams.FILL_PARENT));
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.RED);
p.setStrokeWidth(5);
canvas.drawLine(50, 50, 100, 150, p);
canvas.drawLine(100, 150, 20, 50, p);
}
}
This activity has a framelayout which has a imageview as the base which holds the bitmap.
We add a custom draw view on top of it and do our drawings on it.When we want to clear the drawing we remove the drawview and add another one if we need to draw again.
This might not be the most efficient way. But should get you started.