Custom viewgroup is not showing its child custom views - java

The draggablepointviews in pathview arent showing up. I did addView in PathView but the pointviews are still not being rendered. Am I missing something? I thought addView was enough and would make the childs render.
PathView.kt
class PathView(context: Context) : ViewGroup(context)
{
private val pointA = DraggablePointView(context)
private val pointB = DraggablePointView(context)
private val paint = Paint().apply {
strokeWidth = 15f
color = Color.WHITE
}
init
{
pointA.x = 50f
pointA.y = 50f
pointB.x = 330f
pointB.y = 330f
addView(pointA, 100, 100)
addView(pointB, 100, 100)
setWillNotDraw(false)
}
override fun onDraw(canvas: Canvas?)
{
if (canvas == null)
return
// Draw a line between pointA and pointB
canvas.drawLine(pointA.x, pointA.y, pointB.x, pointB.y, paint)
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int)
{
}
}
DraggablePointView.kt
class DraggablePointView(context: Context) : ImageView(context)
{
init
{
setImageResource(R.drawable.point)
setWillNotDraw(false)
}
override fun onDragEvent(event: DragEvent?): Boolean
{
println("DRAG EVENT")
if (event == null)
return false
x = event.x
y = event.y
return true
}
}
Then:
val pathView = PathView(context)
frameLayout.addView(pathView)

1) Draw the line
To force a view to draw, call invalidate().
void invalidate()
Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future.
void invalidate (int l, int t, int r, int b)
Mark the area defined by the rect (l, t, r, b) as needing to be drawn. The coordinates of the dirty rect are relative to the view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future.
2) Draw the points
Since you extend ViewGroup you're responsible for measuring and laying out the child views.
Perhaps you should extend AbsoluteLayout instead, which already has the measurement and layout logic programmed. Then you can set the coordinates like so:
val lp = layoutParams as AbsoluteLayout.LayoutParams
lp.x = event.x
lp.y = event.y
requestLayout()
Or perhaps you should extend View and draw the points in the same fashion as the line. That should be most efficient. You don't need child views to draw, you need just canvas.
Override onTouchEvent to listen for and react to touch.
Draw the drawable to canvas by calling setBounds (tell it where to draw) and draw.

Related

Canvas; How to remove shapes retroactively

So I am using onDraw in a custom View class to draw shapes on a RelativeLayout + TableLayout all that works fine, and I have another class that I use to draw lines from Point A to Point B etc. example below:
My Goal:
If I drag my finger from Point A (objectA) to Point B(objectB), how can I delete those 2 View Objects from the canvas? I added a method:
objectA.delete();
objectB.delete();
that should delete both A and B when I drag my finger through MotionEvent, but it only deletes one and not the other, so i am thinking it's not retroactive?
Codes below:
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
/// get the child that corresponds to the first touch
DotView objectA = getChildForTouch((TableLayout) v, x, y);
return true;
case MotionEvent.ACTION_MOVE:
///used the x - y to get the object for every other shape the user`S finger passes over.
DotView objectB = getChildForTouch((TableLayout) v, x, y);
/// just update positions
line.setCoords(mStartX, mStartY, (int) x, (int) y);
objectA.delete(); ///Delete first shape
objectB.delete(); ///Delete second shape
break;
case MotionEvent.ACTION_UP:
///Gets the last shape where the user released their fingers
endView = getChildForTouch((TableLayout) v, x, y);
break;
Delete method inside the: DotView extends View class:
private static class DotView extends View {
private static final int DEFAULT_SIZE = 100;
private Paint mPaint = new Paint();
private Rect mBorderRect = new Rect();
private Paint mCirclePaint = new Paint();
private int mRadius = DEFAULT_SIZE / 4;
public DotView(Context context) {
super(context);
mPaint.setStrokeWidth(2.0f);
mPaint.setStyle(Style.STROKE);
mPaint.setColor(Color.RED);
mCirclePaint.setColor(Color.CYAN);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.parseColor("#0099cc"));
mBorderRect.left = 0;
mBorderRect.top = 0;
mBorderRect.right = getMeasuredWidth();
mBorderRect.bottom = getMeasuredHeight();
canvas.drawRect(mBorderRect, mPaint);
canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2,
mRadius, mCirclePaint);
}
public void delete(){
mPaint.setColor(Color.TRANSPARENT);
}
}
Just something simple to fake delete the circles
Thanks in advance guys.. more codes can be provided if need be.
Edit: If I can accomplish this in any other way please feel free to share. (Draw circles on a Grid and delete the ones I used my finger to draw my line over)
First of all try changing your delete() method to this:
public void delete(){
mPaint.setColor(Color.TRANSPARENT);
invalidate();
}
You need to let your View know that you want it to redraw itself (that's why the invalidate() call).

Change ImageResource Dinamically in Custom ImageView Android

I've working in this error all day and can not solve it. I have a custom ImageView as follows:
public class UserDirectionView extends ImageView {
private float mDirection;
private Drawable arrow;
private boolean mCorrectPosition;
// constructors...
#Override
protected void onDraw(Canvas canvas) {
if (arrow == null) {
arrow = getDrawable();
arrow.setBounds(0, 0, getWidth(), getHeight());
// setImageResource(resId); // Not working
}
canvas.save();
canvas.rotate(mDirection, getWidth() / 2, getHeight() / 2);
arrow.draw(canvas);
canvas.restore();
}
public void updateDirection(float direction, boolean correctPos) {
mDirection = direction;
mCorrectPosition = correctPos;
invalidate();
}
}
I am trying to change the imageResource with setImageResource(resId) but nothing is happening. I've tried to call the method inside of onDraw and also outside my class, like so:
UserDirectionView mUserHint = findview....;
mUserHint.setImageResource(resId);
But the image is not changing.
I've also tried to call invalidate, but didn't work.
How could I change the image resource dinamically?
You are missing the super.onDraw() call, which takes care of updating the drawable. Add
super.onDraw(canvas)
In your onDraw

Xamarin Android Vertical ViewPager

I need a vertical ViewPager in Android using Xamarin and the solution doesn't work. I searched some examples in java but there's an object developed by the git community that do all the work. Unfortunately there isn't in Xamarin. So, this is my code, it doesn't give me error, but it displays only a black screen. Nothing more.
I Extended the ViewPager class
public class VerticalViewPager : ViewPager {
public VerticalViewPager (Context context):base(context) {
Init ();
}
public VerticalViewPager(Context context, IAttributeSet attr):base(context, attr) {
Init();
}
public override bool OnTouchEvent (Android.Views.MotionEvent e) {
e.SetLocation (e.GetY (), e.GetX ());
return base.OnTouchEvent (e);
}
private void Init() {
SetPageTransformer (true, new PagerTransformer());
OverScrollMode = Android.Views.OverScrollMode.Never;
}
}
and create my PageTransformer
public class PagerTransformer : Java.Lang.Object, ViewPager.IPageTransformer {
int pageWidth;
int pageHeight;
float yPos;
public PagerTransformer () {}
public void TransformPage (View view, float position) {
pageWidth = view.Width;
pageHeight = view.Height;
if (position < -1) {
view.Alpha = 0;
}
else if (position <= 1) {
view.Alpha = 1;
// Counteract the default slide transition
view.TranslationX = (pageWidth * -position);
//set Y position to swipe in from top
yPos = position + pageHeight;
view.TranslationY = yPos;
}
else {
// This page is way off-screen to the right.
view.Alpha = 0;
}
}
}
In the MainActivity, onCreate method i set
page = FindViewById<VerticalViewPager> (Resource.Id.vertical_pager);
and obviously page is a VerticalViewPager object.
If I use a normale ViewPager, the app works fine. Any ideas about the reason of the black screen?
Any java code is appreciare as well!
Thanks
The reason of black screen is that you set your screen position out of visible bounds. Your visible bounds are from 0 to page height.
Try his : "yPos = position * pageHeight;" instead of "yPos = position + pageHeight;"

How to get (x,y) cordinates of image in android?

I have drawn a image on ONTOUCH with (X,Y)cordinates while moving the image it's cordinates should move along with the image when it reaches it end point the image should be drawn there or else the image should go back to it's starting position.
For eg:(in our mobile if kepad lock we will drag it to open if it reaches it end point the lock will open or else the image will reaches it's starting position).
Reffered link:http://www.vogella.com/tutorials/AndroidTouch/article.html
Here is my code:
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mLocked) {
return false;
}
final int action = event.getAction();
float x = event.getX();
float y = event.getY();
if (mOnDrawerScrollListener != null) {
mOnDrawerScrollListener.onScrollStarted();
}
final int pt = getSide();
mTouchDelta = (int)(y - pt);
prepareTracking(pt);
mVelocityTracker.addMovement(event);
final Rect frame = mFrame;
final View handle = mHandle;
If anyone have idea about this please help me friends.
If you want to get(x, y) cordinates of view (ImageView), just use view.getX(), view.getY(). But when you get it in onCreate(), the results will be (0, 0), because it is not created yet. You should use view.getX(), view.getY() in onGlobalLayoutListener(). For e.g:
rlRoot.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
rlRoot.getViewTreeObserver().removeGlobalOnLayoutListener(this);
Log.d("X", view.getX()+"");
Log.d("Y", view.getY()+"");
}
});
With rlRoot is the layout includes your view and view may be ImageView or any View.
Try it, hope it help.

How to add a view to a specifc point on mapView

an When an onTouch event occurs on my MapView, i want layout i have specified to be drawn above the where the user has touched
The below is where i have started, i do not know how to actually place the popup view on the x and y values retrieved from the event. Do you guys have any ideas?
#Override
public boolean onTouchEvent(MotionEvent ev, MapView mapView) {
int X = (int)ev.getX();
int Y = (int)ev.getY();
ViewGroup parent=(ViewGroup)map.getParent();
View popup=getLayoutInflater().inflate(R.id.popup, parent, false);
((ViewGroup)map.getParent()).addView(popup);
You can set the MapView.LayoutParams() with the values of x and y and then call the MapView's addView with the LayoutParams.
MapView.LayoutParams params = new MapView.LayoutParams(width, height, x, y, alignment);
mapView.addView(popup, params);
At first, your need one global Point with your X,Y coordinates
#Override
public boolean onTouchEvent(MotionEvent ev, MapView mapView) {
int X = (int)ev.getX();
int Y = (int)ev.getY();
selectedPoint = new Point(X,Y);
return true;
}
Now, you should override the onDraw() method to draw you popup view. There are many solutions to do that, I've tried this one with StaticLayout:
#Override
public void draw (Canvas canvas, MapView mapView, boolean shadow){
super.draw(canvas, mapView, false);
if ( selectedPoint != null) {
// here you should define PopupText, textPaint and width variables
StaticLayout sl = new StaticLayout(popupText, textPaint, width,
Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
// here you can draw a rectangle — border for your popup text.
// You can use sl.getWidth() and sl.getWidth() methods to get the popup dimensions
canvas.save();
canvas.translate(selectedPoint.x, selectedPoint.y);
sl.draw(canvas);
canvas.restore()
}
}

Categories