I want to achieve an effect similar to this using the MPAndroidChart library
I want my label to be attached to the Chart line or at least be close to it. Is something like this possible using this library? Or is there a walkaround for this? Something that will have a similar result
A possible way is to use the marker, chart.setMarker(), but marker only shows when user tap on the chart, if you want the marker to show constantly, an custom chart can be invoked and override the function drawMarkers like this, the marker is drawn in the middle of chart:
#Override protected void drawMarkers(Canvas canvas) {
int j = 0;
IDataSet set = mData.getDataSetByIndex(j);
int i = set.getEntryCount() / 3;
Entry e = set.getEntryForIndex(i);
Highlight highlight = new Highlight(e.getX(), e.getY(), i);
highlight.setDataIndex(j);
// callbacks to update the content
mMarker.refreshContent(e, highlight);
MPPointD pix = getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY());
highlight.setDraw((float)pix.x, (float)pix.y);
// draw the marker
float[] pos = getMarkerPosition(highlight);
mMarker.draw(canvas, pos[0], pos[1]);
}
Picture as below, the yellow tag is the marker, it is displayed constantly and without a user tap:
----Updated July 5th
In the demo LineChartActivity1(https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java), line 98, chart.setMarker(mv); sets the Marker, and it allocated by new an MyMarkerView. The drawMarkers can be added at https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java, but it's better to use a customed Chart extends from LineChart
Related
I'm developing a kids alphabets learning application. I need to get the X and Y coordinates of the whole text area from a textview to allow them to draw over the text only. For Example: I have a letter A in my text view, I need to allow the user to draw the letter only over the A text only and need to block the drawing outside the text.
My only problem is I don't know how to find the text area for alphabets as I have increased the font size for the text to display bigger and center aligned it in the screen.
Any suggestions will be really helpful.
Something like this (https://www.youtube.com/watch?v=15B3L78jWfI)?
To stop user from drawing outside of the given area, overriding (12:22) onTouchEvent() you could just put a clause checking whether the given coordinates are inside, or not.
To check if they are inside, you could write such a simple function:
int MIN_X;
int MAX_X;
int MIN_Y;
int MAX_Y;
boolean isInside(int xCord, int yCord){
if(xCord>=MIN_X && xCord<=MAX_X && yCord>=MIN_Y && yCord<=MAX_Y)
return true;
return false;
}
You'd only have to override the min and max values, each time the chosen area changes.
Try the below mentioned code:
ViewTreeObserver vto = textView.getViewTreeObserver();
vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Initialize a new integer array two hold the TextView x y position
int[] location = new int[2];
textView.getLocationOnScreen(location);
}
});
I am using Achart Engine Line chart to display values, i am using point style CIRCLE.
I am trying to implementing the below :
1) Increase the point style width - i mean the circle should be bit bigger.
2) On click of each point i want a popup to be displayed on top of that which will display the values of X and Y.
I have done some research on this but was not able to find the solution.
I found this code but how to display the small popup with values ?
final LineChart chart = new LineChart(buildDataset(mTitles, data), mRenderer);
final GraphicalView view = new GraphicalView(mContext, chart);
view.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
double[] xy = chart.toScreenPoint(view.toRealPoint(0));
int[] location = new int[] {(int) xy[0], (int) xy[1]};
SeriesSelection seriesSelection = view.getCurrentSeriesAndPoint();
if (seriesSelection != null) {
final Data d = mModel.getDiaryAt(seriesSelection.getSeriesIndex(),
seriesSelection.getPointIndex());
//show popup at xy[0] xy[1]
}
}
});
It might have been not given in the SDK but still if anyone has tried this as was successful.
** EDIT **
Link 1 : achartengine toScreenPoint(double) always returns nullPointerException
In the image you can see a popup i want to implement like that.
You can see an example here on how to display the clicked point in your chart, using AChartEngine.
I want to draw several pie chart by using a for loop, and the data is stored in an array (data[][][]). When each chart draw is completed, I make the top and bottom plus 450 (top+=450; bottom+=450;) to avoid the charts to overlap. But the result is that a pie chart moves to the bottom constantly. I try to add invalidate() at the end of line but it doesn't work.
private String data[][][]=... //store some data
private float left=50,top=100,right=450, bottom=500;
public void onDraw(Canvas c) {
super.onDraw(c);
Paint paint = new Paint();
RectF rec;
for(int j=0;j<data.length;j++){
rec=new RectF(left,top,right,bottom);
//draw a pie chart
for (int i = 0; i < data[j].length; i++) {
float drawDegree = (float)Integer.parseInt(data[j][i][1])/100* 360f;
c.drawArc(rec, -90, drawDegree, true, paint);
}
top+=450;
bottom+=450;
}
}
top and bottom are instance variables. Try to make them local, move them to onDraw method. Now you change them every time onDraw called and they don't reset to top=100,bottom=500 after onDraw finished.
The title of your question is pretty misleading... does not sound like there is really any endless loop there.
You should initialize top and bottom in your onDraw function. So you start from the "top" of the screen every time you draw.
Also, you should try to not allocate a new Rect for every pie chart.
Try to allocate one, use offsetTo(50,100) and then use offset(0, 450) to move it down.
Calling invalidate() every time will just make your pie charts being drawn again and again...probably will not do much good.
I am working on an Android app that displays multiple markers on a Google MapView. Everything works perfectly but I would like the markers to have an animation when they appear on the map.
Here's an example of something similar on iPhone. See 1'20".
Here is how I add them to my MapView.
for(int i=0; i<myMarkerList.length(); i++){
GeoPoint x = new GeoPoint(
(int)(lat*1E6),
(int)(lng*1E6));
oItem = new OverlayItem(x, title, String.valueOf(nb_marker));
pin.setAlpha(255);
oItem.setMarker(pin);
if (oItem != null)
mapOverlay.addOverlay(oItem); // add the overlay item to the overlay
}
mapOverlays.add(mapOverlay); // add the overlay to the list of overlays
mapView.invalidate(); // update the map shown
It is so pretty on iPhone, and someone must have already done something similar on Android but I can't seem to find any useful info.
EDIT: Okay so I recon I either have to override the draw method which will be long and not that pretty, or just give up with OverlayItems.
Thank you for your time.
Best regards,
Tom
You can use this tutorial for a reference, it uses animations, so I think that suits your solution.
Code from the tutorial :
//Reference to our MapView
MapView mapView = (MapView) activity.findViewById(R.id.mapview);
//Get a LayoutInflater and load up the view we want to display.
//The false in inflater.inflate prevents the bubble View being added to the MapView straight away
LayoutInflater inflater = activity.getLayoutInflater();
LinearLayout bubble = (LinearLayout) inflater.inflate(R.layout.bubble, mapView, false);
//Set up the bubble's close button
ImageButton bubbleClose = (ImageButton) bubble.findViewById(R.id.bubbleclose);
bubbleClose.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Animation fadeOut = AnimationUtils.loadAnimation(ResultsMapResultsDisplayer.this.activity, R.anim.fadeout);
bubble.startAnimation(fadeOut);
bubble.setVisibility(View.GONE);
}
});
private void displaySearchResultBubble(final SearchResult result) {
//Hide the bubble if it's already showing for another result
map.removeView(bubble);
bubble.setVisibility(View.GONE);
//Set some view content
TextView venueName = (TextView) bubble.findViewById(R.id.venuename);
venueName.setText(result.getName());
//This is the important bit - set up a LayoutParams object for positioning of the bubble.
//This will keep the bubble floating over the GeoPoint result.getPoint() as you move the MapView around,
//but you can also keep the view in the same place on the map using a different LayoutParams constructor
MapView.LayoutParams params = new MapView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
result.getPoint(), MapView.LayoutParams.BOTTOM_CENTER);
bubble.setLayoutParams(params);
map.addView(bubble);
//Measure the bubble so it can be placed on the map
map.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
//Runnable to fade the bubble in when we've finished animatingTo our OverlayItem (below)
Runnable r = new Runnable() {
public void run() {
Animation fadeIn = AnimationUtils.loadAnimation(activity, R.anim.fadein);
bubble.setVisibility(View.VISIBLE);
bubble.startAnimation(fadeIn);
}
};
//This projection and offset finds us a new GeoPoint slightly below the actual OverlayItem,
//which means the bubble will end up being centered nicely when we tap on an Item.
Projection projection = map.getProjection();
Point p = new Point();
projection.toPixels(result.getPoint(), p);
p.offset(0, -(bubble.getMeasuredHeight() / 2));
GeoPoint target = projection.fromPixels(p.x, p.y);
//Move the MapView to our point, and then call the Runnable that fades in the bubble.
mapController.animateTo(target, r);
}
I seen your example app. From that i think you need only Glow in your markers, right? If yes then its possible through the styles and its having glow property also.
So I got it to work using a simple ArrayList of ImageViews and animation on them, no MapOverlay.
I am using this example: https://github.com/galex/android-mapviewballoons
My problem is that the clickable area is wider than the marker itself. For example, my Google Map marker is 25x25 then the clickable area would extend up to 70x70. This is a big problem for overlapping markers.
When I clicked on the tip of that arrow, onTap is activated, even though the tap area is far from the marker.
Please help me. Thanks.
This is the default behaivior of ItemizedOverlay. 25x25 px is generally not an adquate touchable area for most human fingers.
You should override the hitTest() method if you want to modify the way an overlay item hit is tested.
For debugging :
Try using a TouchDelegate for the View, you can specify the Touch rect for a give View
An example showing how to use the TouchDelegate :
public class TouchDelegateSample extends Activity {
Button mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touch_delegate_view);
mButton = (Button)findViewById(R.id.delegated_button);
View parent = findViewById(R.id.touch_delegate_root);
// post a runnable to the parent view's message queue so its run
after
// the view is drawn
parent.post(new Runnable() {
#Override
public void run() {
Rect delegateArea = new Rect();
Button delegate = TouchDelegateSample.this.mButton;
delegate.getHitRect(delegateArea);
delegateArea.top -= 200;
TouchDelegate expandedArea = new TouchDelegate(delegateArea,
delegate);
// give the delegate to an ancestor of the view we're
delegating the
// area to
if (View.class.isInstance(delegate.getParent())) {
((View)delegate.getParent()).setTouchDelegate(expandedArea);
}
}
});
}
}
hitTest()
See if a given hit point is within the bounds of an item's marker. Override to modify the way an item is hit tested. The hit point is relative to the marker's bounds. The default implementation just checks to see if the hit point is within the touchable bounds of the marker.