How to show highlight in LineChart only when chart in press state or drag state? - mpandroidchart

I need to repeat similar behavior to Google Fit charts. When chart is pressed or dragging - we show highlighter on chart. Right after finger don't touch chart - remove highlighter. I found "onTap" variable for tap on chart - but it's work only when we tap and then remove finger from screen. But i need to show highlighter right after finger touched chart

The MakerView and OnChartGestureListener can help, onChartGestureEnd tells when should the marker should disappear:
final MyMarkerView marker = new MyMarkerView(this, R.layout.custom_marker_view);
chart.setMarker(marker);
chart.setDrawMarkers(true);
chart.setOnChartGestureListener(new OnChartGestureListener() {
#Override
public void onChartGestureStart(MotionEvent me,
ChartTouchListener.ChartGesture lastPerformedGesture) {
chart.setDrawMarkers(true);
for(int i = 0; i < chart.getLineData().getDataSetCount(); ++i) {
ILineDataSet set = chart.getLineData().getDataSetByIndex(i);
set.setHighlightEnabled(true);
}
// Thanks to Mr. SoulReaver313 !
chart.highlightValue(chart.getHighlightByTouchPoint(me.getX(), me.getY()));
}
#Override
public void onChartGestureEnd(MotionEvent me,
ChartTouchListener.ChartGesture lastPerformedGesture) {
chart.setDrawMarkers(false);
for(int i = 0; i < chart.getLineData().getDataSetCount(); ++i) {
ILineDataSet set = chart.getLineData().getDataSetByIndex(i);
set.setHighlightEnabled(false);
}
chart.invalidate();
}
#Override
public void onChartLongPressed(MotionEvent me) {
}
#Override
public void onChartDoubleTapped(MotionEvent me) {
}
#Override
public void onChartSingleTapped(MotionEvent me) {
}
#Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX,
float velocityY) {
}
#Override
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
}
#Override
public void onChartTranslate(MotionEvent me, float dX, float dY) {
}
});

Related

How to compare which drawable is in an imageview with a user spinner selection

Currently I am displaying a random image using math.random, this part works but I need to check if the users selection from the dropdown list matches this. The only part I can get to work is the incorrect selection displaying the correct name of the car displayed.
My comparison function never becomes true as Im not sure how to compare the tag of the imageview with a random int
See below my activity
public class IdentifyTheBrandActivity extends AppCompatActivity implements AdapterView.OnItemClickListener,
AdapterView.OnItemSelectedListener { String[] Brands = { "Audi", "Bentley", "BMW" };
Button SubmitButton;
ImageView imageView;
int[] images;
int chosenCar;
int locationOfCorrectAnswer;
String[] answers = new String[3];
ArrayList<String> carBrands = new ArrayList<>();
public void brandChosen(View view) {
if (imageView.getTag().toString().equals(carBrands.get(locationOfCorrectAnswer))){
Toast.makeText(getApplicationContext(), "Correct", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplicationContext(), "Wrong it was " + carBrands.get(locationOfCorrectAnswer), Toast.LENGTH_LONG).show();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_identify_the_brand);
imageView = findViewById(R.id.RandomImage);
imageView.setTag("bg");
carBrands.add("Audi");
carBrands.add("Bentley");
carBrands.add("BMW");
images = new int[]{R.drawable.audi_a3_2010_27_17_200_20_4_77_56_169_21_fwd_5_4_4dr_igm, R.drawable.bentley_bentayga_2017_229_21_600_60_12_78_68_202_12_awd_5_4_suv_cce,
R.drawable.bmw_6_series_2014_82_18_310_30_6_74_53_192_20_rwd_4_2_convertible_mua};
imageView.setTag(R.drawable.audi_a3_2010_27_17_200_20_4_77_56_169_21_fwd_5_4_4dr_igm);
imageView.setTag(R.drawable.bentley_bentayga_2017_229_21_600_60_12_78_68_202_12_awd_5_4_suv_cce);
imageView.setTag(R.drawable.bmw_6_series_2014_82_18_310_30_6_74_53_192_20_rwd_4_2_convertible_mua);
if (imageView.getTag() != null) {
int resourceID = (int) imageView.getTag();
}
Random random = new Random();
chosenCar = random.nextInt(3);
locationOfCorrectAnswer = chosenCar;
imageView.setBackgroundResource(images[chosenCar]);
int incorrectAnswerLocation;
//Get a random between 0 and images.length-1
//int imageId = (int) (Math.random() * images.length);
Spinner spin = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, Brands);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spin.setAdapter(adapter);
spin.setOnItemSelectedListener(this);
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long l) {
Toast.makeText(getApplicationContext(), "Selected Brand: " + Brands[position]
,Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
}
I tried comparing the imageview and the randomly assigned index to the array but it never becomes true
Essentially my issue is how to compare which drawable is actively in the imageview with the users selection

How to draw several lines slowly in constant velocity on canvas by Android?

I need capture the mark to draw a figure on canvas in Android, and the effect just like the follow gif:
Well, as far, I can draw a side with constant velocity by ValueAnimator. However, I just only can draw one side at one time, because I can't save the last side when drawing the next side. So, is there a good way to solve the problem?
Code for draw a line slowly by ValueAnimator:
GraphicsView.java
public class GraphicsView extends View {
private int stepX, stepY = 0;
private int startX, startY, stopX, stopY = 0;
private Paint paint = null;
public GraphicsView(Context context) {
super(context);
// Paint
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
startX = 40;
startY = 397;
stopX = 1040;
stopY = 397;
Init();
}
public void Init(){
ValueAnimator animatorX = ValueAnimator.ofFloat(startX, stopX);
ValueAnimator animatorY = ValueAnimator.ofFloat(startY, stopY);
animatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
stepX = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();
}
});
animatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
stepY = Math.round((Float)valueAnimator.getAnimatedValue()); invalidate();
}
});
AnimatorSet set = new AnimatorSet();
LinearInterpolator l = new LinearInterpolator();
set.setInterpolator(l);
set.setDuration(3000);
set.playTogether(animatorX, animatorY);
set.start();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(startX, startY, stepX, stepY, paint);
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private Display display = null;
private GraphicsView view = null;
private ConstraintLayout layout = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
display = getWindowManager().getDefaultDisplay();
layout = (ConstraintLayout)findViewById(R.id.main_layout);
view = new GraphicsView(this);
view.setMinimumWidth(display.getWidth());
view.setMinimumHeight(display.getHeight());
layout.addView(view);
}
}
you can use the ObjectAnimator class to callback
to one of your class methods every time you'd like to draw a bit more of the path.
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;
import android.util.Log;
public class PathView extends View
{
Path path;
Paint paint;
float length;
public PathView(Context context)
{
super(context);
}
public PathView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public PathView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
public void init()
{
paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
path.moveTo(50, 50);
path.lineTo(50, 500);
path.lineTo(200, 500);
path.lineTo(200, 300);
path.lineTo(350, 300);
// Measure the path
PathMeasure measure = new PathMeasure(path, false);
length = measure.getLength();
float[] intervals = new float[]{length, length};
ObjectAnimator animator = ObjectAnimator.ofFloat(PathView.this, "phase", 1.0f, 0.0f);
animator.setDuration(3000);
animator.start();
}
//is called by animtor object
public void setPhase(float phase)
{
Log.d("pathview","setPhase called with:" + String.valueOf(phase));
paint.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();//will calll onDraw
}
private static PathEffect createPathEffect(float pathLength, float phase, float offset)
{
return new DashPathEffect(new float[] { pathLength, pathLength },
Math.max(phase * pathLength, offset));
}
#Override
public void onDraw(Canvas c)
{
super.onDraw(c);
c.drawPath(path, paint);
}
}
Then, just call init() to begin the animation, like this (or if you'd like it to start as soon as the view is inflated, put the init() call inside the constructors):
PathView path_view = (PathView) root_view.findViewById(R.id.path);
path_view.init();
Also see this question here, and
Using Value Animator Example
Reference 1
Reference 2
Reference 3

Eclipse plugin - ColumnLabelProvider display only image

So I am developing an Eclipse plug-in and using ColumnLabelProvider to provide label for the columns of my tree viewer.
However, in one of the columns, I only intend to display an image and no text. However, in the final display, Eclipse reserves blank space for the text element even if I return a null.
Is there any way to make it display only image and in the full space provided?
Here is the code snippet:
column4.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
return null;
}
#Override
public Image getImage(Object element) {
/* Code to Display an image follows */
.....
}
});
ColumnLabelProvider will always leave space for the text.
You can use a class derived from OwnerDrawLabelProvider to draw the column yourself.
Something like:
public abstract class CentredImageCellLabelProvider extends OwnerDrawLabelProvider
{
protected CentredImageCellLabelProvider()
{
}
#Override
protected void measure(Event event, Object element)
{
}
#Override
protected void erase(final Event event, final Object element)
{
// Don't call super.erase() to suppress non-standard selection draw
}
#Override
protected void paint(final Event event, final Object element)
{
TableItem item = (TableItem)event.item;
Rectangle itemBounds = item.getBounds(event.index);
GC gc = event.gc;
Image image = getImage(element);
Rectangle imageBounds = image.getBounds();
int x = event.x + Math.max(0, (itemBounds.width - imageBounds.width) / 2);
int y = event.y + Math.max(0, (itemBounds.height - imageBounds.height) / 2);
gc.drawImage(image, x, y);
}
protected abstract Image getImage(Object element);
}

Libgdx - camera.unproject is not fixing my coordinates

The following code gives me very strange y coordinates.
10-18 00:13:36.834 30543-30567/com.xxxx.yyyy.android I/x﹕ 137.4782
10-18 00:13:36.834 30543-30567/com.xxxx.yyyy.android I/y﹕ -1984.2426
10-18 00:13:36.835 30543-30567/com.xxxx.yyyy.android I/ux﹕ 91.65213
10-18 00:13:36.835 30543-30567/com.xxxx.yyyy.android I/uy﹕ -1984.2426
I imagine I set up everything wrong rather than do it wrong while running?
The camera.unproject call should take care of all remapping from screen coordinates to game coordinates, shouldn't it? Or do i have to scale and invert before unprojecting?
package com.xxxx.yyyy;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
public class LetterActor extends Actor
{
private Texture texture;
private Vector3 touchPosition = new Vector3();
private Camera camera;
private boolean unproject = true;
public LetterActor(Texture letterTexture, Camera theCamera)
{
texture = letterTexture;
camera = theCamera;
touchPosition.set(240, 800, 0);
camera.unproject(touchPosition);
setPosition(touchPosition.x, touchPosition.y);
setSize(texture.getWidth(), texture.getHeight());
addListener(new InputListener()
{
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
touchPosition.set(x, y, 0);
if (unproject)
{
camera.unproject(touchPosition);
}
setPosition(touchPosition.x, touchPosition.y);
logPositions(x, y, touchPosition.x, touchPosition.y);
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
touchPosition.set(x, y, 0);
if (unproject)
{
camera.unproject(touchPosition);
}
setPosition(touchPosition.x, touchPosition.y);
logPositions(x, y, touchPosition.x, touchPosition.y);
}
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer)
{
touchPosition.set(x, y, 0);
if (unproject)
{
camera.unproject(touchPosition);
}
setPosition(touchPosition.x, touchPosition.y);
logPositions(x, y, touchPosition.x, touchPosition.y);
}
});
}
private void screenTo()
{
}
private void logPositions(float x, float y,float ux, float uy)
{
Gdx.app.log("x", Float.toString(x));
Gdx.app.log("y", Float.toString(y));
Gdx.app.log("ux", Float.toString(ux));
Gdx.app.log("uy", Float.toString(y));
}
#Override
public void draw(Batch batch, float alpha)
{
batch.draw(texture, getX(), getY(), getWidth(), getHeight());
}
#Override
public void act(float delta) {}
}
package com.xxxx.yyyy;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class WordPuzzle extends ApplicationAdapter
{
private final static float VIRTUAL_WIDTH = 480;
private final static float VIRTUAL_HEIGHT = 800;
private OrthographicCamera camera;
private FitViewport viewport;
private Stage stage;
#Override
public void create()
{
camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
camera.setToOrtho(false, VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
viewport = new FitViewport(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, camera);
stage = new Stage();
stage.setViewport(viewport);
Gdx.input.setInputProcessor(stage);
Texture[] textures = LetterLoader.loadLetters();
for (int i = 0; i < textures.length; i++)
{
LetterActor letterActor = new LetterActor(textures[i], camera);
letterActor.setTouchable(Touchable.enabled);
stage.addActor(letterActor);
}
}
#Override
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override public void resize(int width, int height)
{
stage.getViewport().update(width, height, true);
}
#Override public void dispose()
{
stage.dispose();
}
}
package com.xxxx.yyyy;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
public class LetterLoader {
public static Texture[] loadLetters()
{
Texture[] letters = new Texture[26];
for (int i = 0; i < 26; i++)
{
char letter = (char) (i + 65);
letters[i] = new Texture(Gdx.files.internal("bigletters/" + letter + ".png"));
}
return letters;
}
}
First, the touch position (x, y) you get from the input listener are already the correct coordinates.
Concerning your output, you actually print y two times, but call it uy the second time:
Gdx.app.log("uy", Float.toString(y));
If touchPosition.set(240, 800, 0); is in screen coordinates, then you need to unproject them, but
camera.unproject(touchPosition);
assumes that your camera fills the whole screen, thus it calls internally:
unproject(screenCoords, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Since you use a virtual size, this is wrong. The most simple solution would be to use the unproject method from the viewport that you are using:
viewport.unproject(touchPosition);
This will call the camera unproject method with the correct parameters automatically.
Since you are using Stage and InputListener, the coordinates you get in touchDown and the related methods are already in world coordinates, so it doesn't make sense to unproject them. You can use the x and y directly.
Also (although this is irrelevant to InputListener), camera.unproject assumes a Viewport that fills the screen, which is not true of FitViewport, which you're using. If you are using a Viewport class, you need to use viewport.unproject instead of camera.unproject, so it takes the black bars into account.
But you only need to worry about unprojecting for stuff not related to the Stage.

Problems with KeyListener and JOGL

I'm trying to bind a key to translate a GL_QUAD around the screen. I created a class, as I will attach below, that implements KeyListener, and within that I have a method that upon the keypress of 'd', adds 0.1 to the x coordinates of the quad vertices. Now, I have two questions relating to this.
Firstly, it doesn't seem to do anything. Upon the keypress, nothing happens to the object.
Is there a better way to achieve what I am trying to do? My end goal is to eventually end up with a sprite, that the camera is focused upon, that can move around a visually 2D game world.
Thanks for your time.
Code:
SpriteTest.java
package com.mangostudios.spritetest;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.FPSAnimator;
public class SpriteTest
{
public static void main(String[] args) {
GLProfile glp = GLProfile.getDefault();
GLCapabilities caps = new GLCapabilities(glp);
GLCanvas canvas = new GLCanvas(caps);
Frame frame = new Frame("AWT Window Test");
frame.setSize(300, 300);
frame.add(canvas);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
canvas.addGLEventListener(new Renderer());
FPSAnimator animator = new FPSAnimator(canvas, 60);
//animator.add(canvas);
animator.start();
}
}
Renderer.java
package com.mangostudios.spritetest;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
public class Renderer implements GLEventListener {
InputListener input = new InputListener();
#Override
public void display(GLAutoDrawable drawable) {
update();
render(drawable);
}
#Override
public void dispose(GLAutoDrawable drawable) {
}
#Override
public void init(GLAutoDrawable drawable) {
}
#Override
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
}
private void update() {
}
private void render(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
// draw a triangle filling the window
gl.glBegin(GL2.GL_QUADS);
gl.glVertex2f( input.xTran, 0.1f);
gl.glVertex2f( input.xTran,-0.1f);
gl.glVertex2f( -input.xTran, -0.1f);
gl.glVertex2f( -input.xTran, 0.1f);
gl.glEnd();
}
}
InputListener.java
package com.mangostudios.spritetest;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
public class InputListener implements KeyListener{
boolean loopBool = false;
float xTran = 0.1f;
float yTran = 0.1f;
#Override
public void keyPressed(KeyEvent d) {
loopBool = true;
while (loopBool = true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void keyReleased(KeyEvent d) {
}
}
At first, you never call addKeyListener(). Secondly, you shouldn't put an infinite loop into keyPressed(). Thirdly, you use a NEWT KeyListener whereas you use an AWT GLCanvas :s Rather use GLWindow with a NEWT KeyListener or use an AWT GLCanvas with an AWT KeyListener or use NewtCanvasAWT. Finally, before writing your own example, try mine on Wikipedia in order to understand why it works.