MPAndroidChart MarkerView in fixed position - mpandroidchart

Is there any way to have fixed position for MarkerView? I need to have it fixed in top left or top right corner.

This is one approach to fix the marker on the Top Left or Top Right
Once you've created the custom MarkerView here's what you can do.
1) You can set an id to the parent view/layout and using that id you can get it's width.
layoutWidth = customLayout.getWidth();
2) You can then override draw and do the following:
#Override
public void draw(Canvas canvas, float posX, float posY) {
if (posX > (canvas.getWidth() / 2.0))
//Check if the user is in the right half of the canvas
super.draw(canvas, leftXPos, leftYPos);
//Draw marker on the left top corner
else
//Otherwise draw the marker on the top right corner.
super.draw(canvas, canvas.getWidth() - layoutWidth, rightYPos);
}
You can set the values for leftXPos, leftYPos and rightYPos to whatever looks and feels best.
Hope this helps!

You should create a custom MarkerView, like in the documentation.
Then, customize getXOffset and getYOffset like this:
#Override
public int getXOffset(float xpos) {
// this will cause the marker-view to be at left of the screen
return -(int)xpos;
}
#Override
public int getYOffset(float ypos) {
// this will cause the marker-view to be at top screen
return -(int)ypos;

getXOffset(float xpos) and getYOffset(float ypos) are not overridden by the MarkerView class anymore. To fix the Marker position, You have to override the getOffsetForDrawingAtPoint(float posX, float posY) method in the following way:
private MPPointF mOffset;
#Override
public MPPointF getOffsetForDrawingAtPoint(float posX, float posY) {
if(mOffset == null) {
// center the marker horizontally and fixed Y position at the top
mOffset = new MPPointF(-(getWidth() / 2f), -posY);
}
return mOffset;
}

MpandroidChart v3.1.0 :
class MarkerView constructor(
context: Context,
) :
MarkerView(context, R.layout.marker_view) {
private val totalWidth = resources.displayMetrics.widthPixels
override fun refreshContent(e: Entry?, highlight: Highlight?) {
//...
super.refreshContent(e, highlight)
}
override fun getOffsetForDrawingAtPoint(posX: Float, posY: Float): MPPointF {
val supposedX = posX + width
val mpPointF = MPPointF()
mpPointF.x = when {
supposedX > totalWidth -> -width.toFloat()
posX - width < 0 -> 0f
else -> 0f
}
mpPointF.y = if (posY > height)
-height.toFloat()
else
0f
return mpPointF
}
}
in this implementation the default location for MarkerView is to the top-right of the point, if there is enough space, else may be to top-left , bottom-left or bottom-right of it .you can change this behaviour based on your needs.
notice that this only Workes if chart's width is set to MATCH_PARENT.

Related

RecyclerView divider width with ItemDecoration

I have a RecyclerView and have added an ItemDecoration to it as follows :-
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
My ItemDecoration looks like :-
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
{
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++)
{
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
This draws a divider taking full width of the screen. I want to add a little margin from the left and right of about 15dp (red line) so that it looks shorter than the screen width something like below :-
How can I achieve this? Any suggestions are appreciated.
Have a look at getItemOffsets method. Something like following should do it.
override fun getItemOffsets(
rect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
rect.right = parent.right - yourMargin
rect.left = parent.left + yourMargin
}
This method will set the rect space where you'll draw (onDraw(...)) your decoration.
Just put the value of
final int left = 200;
final int right= 200;

XNA 4.0 Camera and object handling on screen

For developing a side-scrolling platform 2D game I want to implement a moving camera class, the reason of using the class instead of moving the whole map is that I'll have to use too many objects at once witch will cause a lag. I cannot let that happen.
There's a nice algorithm for handling the camera, when player is moving further than the width of the screen then camera moves on players direction until he is once again in the middle of the screen, I've been working several days for making this algorithm work however there's been no success.
// Main
public class Camera
{
protected float _zoom;
protected Matrix _transform;
protected Matrix _inverseTransform;
//The zoom scalar (1.0f = 100% zoom level)
public float Zoom
{
get { return _zoom; }
set { _zoom = value; }
}
// Camera View Matrix Property
public Matrix Transform
{
get { return _transform; }
set { _transform = value; }
}
// Inverse of the view matrix,
// can be used to get
// objects screen coordinates
// from its object coordinates
public Matrix InverseTransform
{
get { return _inverseTransform; }
}
public Vector2 Pos;
// Constructor
public Camera()
{
_zoom = 2.4f;
Pos = new Vector2(0, 0);
}
// Update
public void Update(GameTime gameTime)
{
//Clamp zoom value
_zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f);
//Create view matrix
_transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
Matrix.CreateTranslation(Pos.X, Pos.Y, 0);
//Update inverse matrix
_inverseTransform = Matrix.Invert(_transform);
}
}
This is the camera class I made for handling the screen, it's main purpose is to resize the screen, more precisely to zoom in and out whenever I want to change my screen, (Title screen, Playing screen, Game over, and like that.)
Moving the camera is quite simple with keys, like this.
if (keyState.IsKeyDown(Keys.D))
Cam.Pos.X -= 20;
if (keyState.IsKeyDown(Keys.A))
Cam.Pos.X += 20;
if (keyState.IsKeyDown(Keys.S))
Cam.Pos.Y -= 20;
if (keyState.IsKeyDown(Keys.W))
Cam.Pos.Y += 20;
And ofc. the drawing method witch apply the camera.
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, null, null, null, null, Cam.Transform);
Here comes the part when I stop, so what I want to do is make something like 2 2D rooms. By Room I mean the place where I usually place objects. like this "Vector2(74, 63)" So I want to create a place where I could draw items that would stick to the screen and wouldn't move, and make the screen bounds that would make my algorithm to work, witch will be always on screen and as an addition it will check if one of the borders of the screen "room" reaches the certain coordinates of the map "room".
I think that the reason for that would be obvious because I don't want player to move camera outside the map when he reaches the wall, otherwise the player would already see a part of the next map where he will be transformed.
The reason of drawing both maps next to each other is again to reduce the loading time so player wouldn't have to wait for playing the next map.
Alright, so I've run into more troubles than I expected so I'll add extra information and will start with the player class:
// Main
public class Player
{
public Texture2D AureliusTexture;
public Vector2 position;
public Vector2 velocity;
public Vector2 PosForTheCam; // Variable that holds value for moving the camera
protected Vector2 dimensions;
protected CollisionPath attachedPath;
const float GRAVITY = 18.0f;
const float WALK_VELOCITY = 120f;
const float JUMP_VELOCITY = -425.0f;
// Constructor
public Player()
{
dimensions = new Vector2(23, 46);
position = new Vector2(50, 770);
}
public void Update(float deltaSeconds, List<CollisionPath> collisionPaths)
{
#region Input handling
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.Left))
{
velocity.X = -WALK_VELOCITY;
}
else if (keyState.IsKeyDown(Keys.Right))
{
velocity.X = WALK_VELOCITY;
}
else
{
velocity.X = 0;
}
if (attachedPath != null && keyState.IsKeyDown(Keys.Space))
{
velocity.Y = JUMP_VELOCITY;
attachedPath = null;
}
velocity.Y += GRAVITY;
#endregion
#region Region of handling the camera based on Player
PosForTheCam.X = velocity.X;
#endregion
#region Collision checking
if (velocity.Y >= 0)
{
if (attachedPath != null)
{
position.X += velocity.X * deltaSeconds;
position.Y = attachedPath.InterpolateY(position.X) - dimensions.Y / 2;
velocity.Y = 0;
if (position.X < attachedPath.MinimumX || position.X > attachedPath.MaximumX)
{
attachedPath = null;
}
}
else
{
Vector2 footPosition = position + new Vector2(0, dimensions.Y / 2);
Vector2 expectedFootPosition = footPosition + velocity * deltaSeconds;
CollisionPath landablePath = null;
float landablePosition = float.MaxValue;
foreach (CollisionPath path in collisionPaths)
{
if (expectedFootPosition.X >= path.MinimumX && expectedFootPosition.X <= path.MaximumX)
{
float pathOldY = path.InterpolateY(footPosition.X);
float pathNewY = path.InterpolateY(expectedFootPosition.X);
if (footPosition.Y <= pathOldY && expectedFootPosition.Y >= pathNewY && pathNewY < landablePosition)
{
landablePath = path;
landablePosition = pathNewY;
}
}
}
if (landablePath != null)
{
velocity.Y = 0;
footPosition.Y = landablePosition;
attachedPath = landablePath;
position.X += velocity.X * deltaSeconds;
position.Y = footPosition.Y - dimensions.Y / 2;
}
else
{
position = position + velocity * deltaSeconds;
}
}
}
else
{
position += velocity * deltaSeconds;
attachedPath = null;
}
#endregion
}
}
So I state it clear that I asked my friend to do most of it because I wanted to handle the gravity and the slopes so we made it work similar like in Unity. And he happened to know how to do that.
And so I'll add the Update method that handles the camera from the Main Class.
MM.Update(gameTime); // Map Managher update function for map handling
Cam.Update(gameTime); // Camera update
Cam.Zoom = 2.4f; // Sets the zoom level for the title screen
// Takes the start position for camera in map and then turns off the update
// so the camera position can be changed. Else it would just keep an infinite
// loop and we couldn't change the camera.
if (StartInNewRoom)
{
Cam.Pos = MM.CameraPosition; // Applys the camera position value from the map manager class
StartInNewRoom = false;
}
I am unsure how to handle the camera, like I used your method and the result often ended up that camera moves by itself or it doesn't move at all.
If you don't want objects to move with the camera like a HUD you need a second spriteBatch.Begin() without your camera matrix which you draw after your actual scene.
To make the camera not move out of the map you could use some kind of collision detection. Just calculate the right border of your camera. It depends where the origin of your camera is.
Is your camera matrix working like this? Because the position should be negative or it will move in the wrong direction.
This is how mine looks like.
return Matrix.CreateTranslation(new Vector3(-camera.position.X, -camera.position.Y, 0)) *
Matrix.CreateRotationZ(Rotation) * Matrix.CreateScale(Zoom) *
Matrix.CreateTranslation(new Vector3(Viewport.Width * 0.5f, Viewport.Height * 0.5f, 0));
Viewport.Width/Height * 0.5 centers you camera.
You can also apply this behind your Pos.X/Y
To Camera follows player
public void Update(Player player)
{
//Clamp zoom value
_zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f);
//Create view matrix
_transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
Matrix.CreateTranslation(player.Pos.X, player.Pos.Y, 0);
//Update inverse matrix
_inverseTransform = Matrix.Invert(_transform);
}

android reveal animation jerk observer

Hi I am trying to do simple reveal animation in android lollipop. But sudden jerk is observed at the start and end of animation. Can you tell how to overcome this. I tried increasing and decreasing animation duration but it doesn't seems to be working.
package in.ashish29agre.revealfab;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.ViewAnimationUtils;
public class MainActivity extends AppCompatActivity {
private boolean isViewVisible = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(isViewVisible) {
hide(fab, findViewById(R.id.reveal_view));
isViewVisible = false;
} else {
show(fab, findViewById(R.id.reveal_view));
isViewVisible = true;
}
}
});
}
private void show(final View view, final View layoutView) {
// get the center for the clipping circle
int cx = (view.getLeft() + view.getRight()) / 2;
int cy = (view.getTop() + view.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(layoutView.getWidth(), layoutView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim = ViewAnimationUtils.createCircularReveal(layoutView, cx, cy,
0, finalRadius);
anim.setDuration(2000);
// make the view visible and start the animation
layoutView.setVisibility(View.VISIBLE);
anim.start();
}
// To hide a previously visible view using this effect:
private void hide(final View view, final View layoutView) {
// get the center for the clipping circle
int cx = (view.getLeft() + view.getRight()) / 2;
int cy = (view.getTop() + view.getBottom()) / 2;
// get the initial radius for the clipping circle
int initialRadius = layoutView.getWidth();
// create the animation (the final radius is zero)
Animator anim = ViewAnimationUtils.createCircularReveal(layoutView, cx, cy,
initialRadius, 0);
anim.setDuration(1000);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
layoutView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();
}
}
The reveal animation is based on coordinates of the View itself. If the jerk is that the View is suddenly partly hidden while disappearing and suddenly revealed all the way on appear, then that is your culprit. Use:
float cx = getWidth() / 2f;
float cy = getHeight() / 2f;
float radius = (float)Math.sqrt(cx * cx + cy * cy);

My current GPS Position under Nutiteq is not properly updated

as basis for my GPS functionality I've taken HelloMap3D Example of Nutiteq (Thx Jaak) and I adapted to show my current GPS position light different of this example, so, no growing yelow circles but a fix blue translucent circle with a center point as my current Position and works fine except the update. It should erase the past position if location is changed, so that
this update happens as in the example in the method onLocationChanged
This is the code in my Main Activity
protected void initGps(final MyLocationCircle locationCircle) {
final Projection proj = mapView.getLayers().getBaseLayer().getProjection();
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
locationCircle.setLocation(proj, location);
locationCircle.setVisible(true);
}
// Another Methods...
}
}
I have adapted MyLocationCircle Class like this
public void update() {
//Draw center with a drawable
Bitmap bitmapPosition = BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_home);
PointStyle pointStyle = PointStyle.builder().setBitmap(bitmapPosition).setColor(Color.BLUE).build();
// Create/update Point
if ( point == null ) {
point = new Point(circlePos, null, pointStyle, null);
layer.add(point);
} else { // We just have to change the Position to actual Position
point.setMapPos(circlePos);
}
point.setVisible(visible);
// Build closed circle
circleVerts.clear();
for (float tsj = 0; tsj <= 360; tsj += 360 / NR_OF_CIRCLE_VERTS) {
MapPos mapPos = new MapPos(circleScale * Math.cos(tsj * Const.DEG_TO_RAD) + circlePos.x, circleScale * Math.sin(tsj * Const.DEG_TO_RAD) + circlePos.y);
circleVerts.add(mapPos);
}
// Create/update line
if (circle == null) {
LineStyle lineStyle = LineStyle.builder().setWidth(0.05f).setColor(Color.BLUE).build();
PolygonStyle polygonStyle = PolygonStyle.builder().setColor(Color.BLUE & 0x80FFFFFF).setLineStyle(lineStyle).build();//0xE0FFFF
circle = new Polygon(circleVerts, null, polygonStyle, circle_data);
layer.add(circle);
} else {
circle.setVertexList(circleVerts);
}
circle.setVisible(visible);
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public void setLocation(Projection proj, Location location) {
circlePos = proj.fromWgs84(location.getLongitude(), location.getLatitude());
projectionScale = (float) proj.getBounds().getWidth();
circleRadius = location.getAccuracy();
// Here is the most important modification
update();
}
So, each time our Position changes is called onLocationChanged(Location location) Method and there will be called locationCircle.setLocation(location) and last there, it will be called update called.
The questions are, What am I making wrong? and How can I solve it?
Thank you in advance.
You create and add new circle with every update. You should reuse single one, just update vertexes with setVertexList(). In particular this line should be outside onLocationChanged cycle, somewhere in initGPS perhaps:
circle = new Polygon(circleVerts, null, polygonStyle, circle_data);

How to find the Joint coordinates(X,Y,Z) ,also how to draw a locus of the tracked joint?

I am trying to develop a logic to recognize a circle which is made by users right hand, I got the code to draw the skeleton and track from the sample code,
private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
Skeleton[] skeletons = new Skeleton[0];
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null)
{
skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
skeletonFrame.CopySkeletonDataTo(skeletons);
}
}
using (DrawingContext dc = this.drawingGroup.Open())
{
// Draw a transparent background to set the render size
dc.DrawRectangle(Brushes.Black, null, new Rect(0.0, 0.0, RenderWidth, RenderHeight));
if (skeletons.Length != 0)
{
foreach (Skeleton skel in skeletons)
{
RenderClippedEdges(skel, dc);
if (skel.TrackingState == SkeletonTrackingState.Tracked)
{
this.DrawBonesAndJoints(skel, dc);
}
else if (skel.TrackingState == SkeletonTrackingState.PositionOnly)
{
dc.DrawEllipse(
this.centerPointBrush,
null,
this.SkeletonPointToScreen(skel.Position),
BodyCenterThickness,
BodyCenterThickness);
}
}
}
// prevent drawing outside of our render area
this.drawingGroup.ClipGeometry = new RectangleGeometry(new Rect(0.0, 0.0, RenderWidth, RenderHeight));
}
}
What I want to do now is to track the coordinates of users right hand for gesture recognition,
Here is how I am planning to get the job done:
Start the gesture
Draw the circled gesture, Make sure to store the coordinates for start and then keep noting the coordinates for every 45 degree shift of the Joint from the start, for 8 octants we will get 8 samples.
For making a decision that a circle was drawn we can just check the relation ship between the eight samples.
Also, in the depthimage I want to show the locus of the drawn gesture, so as the handpoint moves it leaves a trace behind so at the end we will get a figure which was drawn by an user. I have no idea how to achieve this.
Coordinates for each joint are available for each tracked skeleton during each SkeletonFrameReady event. Inside your foreach loop...
foreach (Skeleton skeleton in skeletons) {
// get the joint
Joint rightHand = skeleton.Joints[JointType.HandRight];
// get the individual points of the right hand
double rightX = rightHand.Position.X;
double rightY = rightHand.Position.Y;
double rightZ = rightHand.Position.Z;
}
You can look at the JointType enum to pull out any of the joints and work with the individual coordinates.
To draw your gesture trail you can use the DrawContext you have in your example or use another way to draw a Path onto the visual layer. With your x/y/z values, you would need to scale them to the window coordinates. The "Coding4Fun" library offers a pre-built function to do it; alternatively you can write your own, for example:
private static double ScaleY(Joint joint)
{
double y = ((SystemParameters.PrimaryScreenHeight / 0.4) * -joint.Position.Y) + (SystemParameters.PrimaryScreenHeight / 2);
return y;
}
private static void ScaleXY(Joint shoulderCenter, bool rightHand, Joint joint, out int scaledX, out int scaledY)
{
double screenWidth = SystemParameters.PrimaryScreenWidth;
double x = 0;
double y = ScaleY(joint);
// if rightHand then place shouldCenter on left of screen
// else place shouldCenter on right of screen
if (rightHand)
{
x = (joint.Position.X - shoulderCenter.Position.X) * screenWidth * 2;
}
else
{
x = screenWidth - ((shoulderCenter.Position.X - joint.Position.X) * (screenWidth * 2));
}
if (x < 0)
{
x = 0;
}
else if (x > screenWidth - 5)
{
x = screenWidth - 5;
}
if (y < 0)
{
y = 0;
}
scaledX = (int)x;
scaledY = (int)y;
}