Every time I call this method it return nullpointerexception:
java.lang.NullPointerException at org.achartengine.chart.XYChart.toScreenPoint(XYChart.java:867)
I see mScreenR of chart is null
Without using this method toScreenPoint(double) the charts works well this is the code:
package com.insights.insights.gui;
import java.util.ArrayList;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import com.insights.insights.R;
import com.insights.insights.local.ApplicationsController;
import com.insights.insights.model.AppMetrics;
import com.insights.insights.model.Application;
import com.insights.insights.model.Applications;
import com.insights.insights.model.Day;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout;
import android.widget.LinearLayout;
import android.widget.Toast;
public class ChartFragment extends Fragment {
private XYMultipleSeriesRenderer renderer;
private XYMultipleSeriesDataset dataset;
private GraphicalView graphicalView;
private XYSeries firstSeries;
private XYChart chart=null;
private String apiKey;
private ArrayList<Day> days;
private View view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apiKey = getArguments().getString(getString(R.string.tabs_activity_api_key));
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.chart_fragment, container, false);
v.findViewById(R.idChartFragment.container).requestFocus();
this.view = v;
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Obtaining data to plot
Applications applications = ApplicationsController.getInstance(getActivity()).getApplications();
ArrayList<Application> applicationArray = applications.getApplication();
if (applicationArray != null && !applicationArray.isEmpty()) {
for (int i = 0; i < applicationArray.size(); i++) {
if (applicationArray.get(i).getApiKey().equals(apiKey)) {
ArrayList<AppMetrics> appMetrics = applicationArray.get(i).getAppMetrics();
for (int j = 0; j < appMetrics.size(); j++) {
if (appMetrics.get(j).getMetric().equals("Sessions")) {
days = appMetrics.get(j).getDay();
break;
}
}
}
}
}
// If there isn't any item to plot and show a toast
if (days == null) {
Toast toast = Toast.makeText(getActivity(), R.string.chart_fragment_no_items, Toast.LENGTH_LONG);
toast.show();
return;
}
// Ploting the items
dataset = getDataset(days);
renderer = getRenderer();
setRendererStyling(renderer);
// add plot to the layout
if (graphicalView == null) {
LinearLayout layout = (LinearLayout) view.findViewById(R.idChartFragment.Chart);
chart= new LineChart(dataset, renderer);
graphicalView = new GraphicalView(getActivity(), chart);
renderer.setSelectableBuffer(11);
layout.addView(graphicalView);
} else{
graphicalView.repaint();
}
if(chart!=null&&firstSeries!=null){
for(int i=0;i<firstSeries.getItemCount();i++){
double x = firstSeries.getX(i);
double y = firstSeries.getY(i);
double[] screenPoint = chart.toScreenPoint(new double[] { x, y },0);
Log.i("puntos", x + "," + y + " = "+" ("+screenPoint[0]+", "+screenPoint[1]+")");
}
}
}
/**
* Method for set the style of the plotter window and the string at the x
* axis
*
* #param mRenderer
* render to put style in
*
* #param dataSetX
* string to set at x axis
*/
private void setRendererStyling(XYMultipleSeriesRenderer mRenderer) {
mRenderer.setApplyBackgroundColor(false);
mRenderer.setMarginsColor(R.drawable.transperent_color);
mRenderer.setMargins(new int[] { 0, 0, 0, 0 });
mRenderer.setShowAxes(false);
mRenderer.setZoomButtonsVisible(false);
mRenderer.setExternalZoomEnabled(false);
mRenderer.setPointSize(20);
mRenderer.setClickEnabled(false);
mRenderer.setDisplayValues(false);
mRenderer.setXLabels(0);
mRenderer.setYLabels(0);
mRenderer.setPanEnabled(false);
mRenderer.setZoomEnabled(false);
mRenderer.setShowLegend(false);
}
/**
* Method to introduce the values of the y axis
*
* #param dataSetY
* data to set at axis y
* #return the data to set
*/
private XYMultipleSeriesDataset getDataset(ArrayList<Day> days) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
firstSeries = new XYSeries("");
for (int i = 0; i < 12; i++) {
int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
firstSeries.add(i, value);
}
dataset.addSeries(firstSeries);
return dataset;
}
/**
* Method for set the style of the line you want to plot and create a new
* renderer
*
* #return the renderer
*/
private XYMultipleSeriesRenderer getRenderer() {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
XYSeriesRenderer r = new XYSeriesRenderer();
r.setColor(getResources().getColor(R.color.grey_number_label_background));
r.setLineWidth(getResources().getInteger(R.integer.chart_fragment_line_width));
// r.setDisplayChartValues(true);
r.setPointStyle(PointStyle.POINT);
r.setFillPoints(true);
renderer.addSeriesRenderer(r);
return renderer;
}
}
And this is the layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+idChartFragment/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<LinearLayout
android:id="#+idChartFragment/Chart"
android:layout_width="300dp"
android:layout_height="300dp"
android:orientation="horizontal"/>
<AbsoluteLayout
android:id="#+idChartFragment/absolute"
android:layout_width="300dp"
android:layout_height="300dp"/>
</RelativeLayout>
Second Edit:
I want to do something like this:
With my code I do this:
This is my code:
package com.insights.insights.gui;
import java.util.ArrayList;
import java.util.List;
import org.achartengine.GraphicalView;
import org.achartengine.chart.ClickableArea;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.SeriesSelection;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Layout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.maps.ItemizedOverlay.OnFocusChangeListener;
import com.insights.insights.R;
import com.insights.insights.local.ApplicationsController;
import com.insights.insights.model.AppMetrics;
import com.insights.insights.model.Application;
import com.insights.insights.model.Applications;
import com.insights.insights.model.Day;
/**
*
* #author Manuel Plazas Palacio
*
*/
public class ChartFragment extends Fragment {
private XYMultipleSeriesRenderer renderer;
private XYMultipleSeriesDataset dataset;
private GraphicalView graphicalView;
private XYSeries firstSeries;
private XYChart chart = null;
private AbsoluteLayout absoluteLayout;
private ImageView point;
private LinearLayout pointInfoConatiner;
private TextView pointNumberText;
private TextView pointNameText;
private TextView pointDateText;
private Typeface avenirHeavy;
private Typeface avenirLight;
private String apiKey;
private String metricName;
private ArrayList<Day> days;
// The max and the min values displayed
private double max = 0;
private double min = 0;
private View view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apiKey = getArguments().getString(getString(R.string.tabs_activity_api_key));
metricName = "Sessions";
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.chart_fragment, container, false);
v.findViewById(R.idChartFragment.container).requestFocus();
this.view = v;
absoluteLayout = (AbsoluteLayout) v.findViewById(R.idChartFragment.absolute);
// pointInfoConatiner = (LinearLayout) v.findViewById(R.idChartFragment.pointInfoContainer);
// pointNumberText = (TextView) v.findViewById(R.idChartFragment.pointNumberText);
// pointNameText = (TextView) v.findViewById(R.idChartFragment.pointNameText);
// pointDateText = (TextView) v.findViewById(R.idChartFragment.pointDateText);
//
// pointNameText.setText(metricName);
// Obtaining data to plot
Applications applications = ApplicationsController.getInstance(getActivity()).getApplications();
ArrayList<Application> applicationArray = applications.getApplication();
if (applicationArray != null && !applicationArray.isEmpty()) {
for (int i = 0; i < applicationArray.size(); i++) {
if (applicationArray.get(i).getApiKey().equals(apiKey)) {
ArrayList<AppMetrics> appMetrics = applicationArray.get(i).getAppMetrics();
for (int j = 0; j < appMetrics.size(); j++) {
if (appMetrics.get(j).getMetric().equals(metricName)) {
days = appMetrics.get(j).getDay();
break;
}
}
}
}
}
// If there isn't any item to plot and show a toast
if (days == null) {
Toast toast = Toast.makeText(getActivity(), R.string.chart_fragment_no_items, Toast.LENGTH_LONG);
toast.show();
}
// Ploting the items
dataset = getDataset(days);
renderer = getRenderer();
setRendererStyling(renderer);
// add plot to the layout
if (graphicalView == null) {
LinearLayout layout = (LinearLayout) view.findViewById(R.idChartFragment.Chart);
chart = new LineChart(dataset, renderer);
graphicalView = new GraphicalView(getActivity(), chart);
renderer.setSelectableBuffer(11);
layout.addView(graphicalView);
} else {
graphicalView.repaint();
}
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
avenirHeavy = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Avenir Heavy.ttf");
avenirLight = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Avenir Light.ttf");
graphicalView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SeriesSelection seriesSelection = graphicalView.getCurrentSeriesAndPoint();
double[] xy = graphicalView.toRealPoint(0);
//creating the views
createOnClickPointsView();
if (seriesSelection != null) {
// debug
Log.d("Punto", seriesSelection.getXValue() + ", " + seriesSelection.getValue());
double x = firstSeries.getX(seriesSelection.getPointIndex() + 1);
double y = firstSeries.getY(seriesSelection.getPointIndex() + 1);
double[] screenPoint = chart.toScreenPoint(new double[] { x, y });
// debug
Log.d("Chart point", "Chart element in series index " + seriesSelection.getSeriesIndex() + " data point index "
+ seriesSelection.getPointIndex() + " was clicked" + " closest point value X=" + seriesSelection.getXValue()
+ ", Y=" + seriesSelection.getValue() + " clicked point value X=" + (float) xy[0] + ", Y=" + (float) xy[1]);
Log.d("Punto pantalla", " (" + screenPoint[0] + ", " + screenPoint[1] + ")");
int value = Integer.parseInt(days.get((int) (days.size() - (13 - x))).getValue());
String date = days.get((int) (days.size() - (13 - x))).getDate();
pointNumberText.setText(value + "");
pointDateText.setText(date);
// drawing point info
absoluteLayout.addView(pointInfoConatiner, new LayoutParams(getResources().getDrawable(R.drawable.graficapin)
.getIntrinsicWidth(), getResources().getDrawable(R.drawable.graficapin).getIntrinsicHeight(),
(int) (screenPoint[0] - (getResources().getDrawable(R.drawable.graficapin).getIntrinsicWidth() / 2)),
(int) (screenPoint[1] - (getResources().getDrawable(R.drawable.graficapin).getIntrinsicHeight()))));
// drawing point clicked
absoluteLayout.addView(point, new LayoutParams(getResources().getDrawable(R.drawable.puntoon).getIntrinsicWidth(),
getResources().getDrawable(R.drawable.puntoon).getIntrinsicHeight(), (int) (screenPoint[0] - (getResources()
.getDrawable(R.drawable.puntoon).getIntrinsicWidth() / 2)), (int) (screenPoint[1] - ((getResources()
.getDrawable(R.drawable.puntoon).getIntrinsicHeight()) / 4))));
}
}
});
}
/**
* Method for set the style of the plotter window and the string at the x
* axis
*
* #param mRenderer
* render to put style in
*
* #param dataSetX
* string to set at x axis
*/
private void setRendererStyling(XYMultipleSeriesRenderer mRenderer) {
mRenderer.setApplyBackgroundColor(false);
mRenderer.setMarginsColor(R.drawable.transperent_color);
mRenderer.setMargins(new int[] { 0, 0, 0, 0 });
mRenderer.setShowAxes(false);
mRenderer.setZoomButtonsVisible(false);
mRenderer.setExternalZoomEnabled(false);
mRenderer.setPointSize(getResources().getInteger(R.integer.chart_fragment_point_size));
mRenderer.setClickEnabled(true);
mRenderer.setDisplayValues(false);
mRenderer.setXLabels(0);
mRenderer.setYLabels(0);
mRenderer.setPanEnabled(true);
mRenderer.setZoomEnabled(false);
mRenderer.setShowLegend(false);
mRenderer.setYAxisMax(max + 10);
mRenderer.setYAxisMin(min - 10);
}
/**
* Method to introduce the values of the y axis
*
* #param dataSetY
* data to set at axis y
* #return the data to set
*/
private XYMultipleSeriesDataset getDataset(ArrayList<Day> days) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
firstSeries = new XYSeries("");
for (int i = 0; i < 12; i++) {
int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
firstSeries.add(i, value);
}
dataset.addSeries(firstSeries);
XYSeries secondSeries = new XYSeries("");
for (int i = 1; i < 11; i++) {
int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
if (i == 1) {
max = value;
min = value;
}
if (value > max)
max = value;
if (value < min)
min = value;
secondSeries.add(i, value);
}
dataset.addSeries(secondSeries);
return dataset;
}
/**
* Method for set the style of the line you want to plot and create a new
* renderer
*
* #return the renderer
*/
private XYMultipleSeriesRenderer getRenderer() {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
//First chart with the line
XYSeriesRenderer r = new XYSeriesRenderer();
r.setColor(getResources().getColor(R.color.grey_number_label_background));
r.setLineWidth(getResources().getInteger(R.integer.chart_fragment_line_width));
// r.setDisplayChartValues(true);
r.setPointStyle(PointStyle.POINT);
r.setFillPoints(true);
renderer.addSeriesRenderer(r);
// Second chart with the points
XYSeriesRenderer r1 = new XYSeriesRenderer();
r1.setColor(getResources().getColor(R.color.purple_chart_points));
r1.setLineWidth(0);
r1.setFillPoints(true);
r1.setPointStyle(PointStyle.CIRCLE);
renderer.addSeriesRenderer(r1);
return renderer;
}
public XYSeries getFirstSeries() {
return firstSeries;
}
public void setFirstSeries(XYSeries firstSeries) {
this.firstSeries = firstSeries;
}
public XYChart getChart() {
return chart;
}
public void setChart(XYChart chart) {
this.chart = chart;
}
/**
* Method for create the views when clicking on a point of the chart
*/
private void createOnClickPointsView() {
//If the info is already visible
if (pointInfoConatiner != null)
absoluteLayout.removeView(pointInfoConatiner);
// If the point is drawn
if (point != null)
absoluteLayout.removeView(point);
pointInfoConatiner = new LinearLayout(getActivity());
pointInfoConatiner.setBackgroundDrawable(getResources().getDrawable(R.drawable.graficapin));
pointInfoConatiner.setOrientation(LinearLayout.VERTICAL);
pointInfoConatiner.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(0, 8, 0, 0);
pointNumberText = new TextView(getActivity());
pointNumberText.setTextSize(18);
pointNumberText.setTextColor(getResources().getColor(R.color.purple_chart_points));
pointNumberText.setTypeface(avenirHeavy);
pointNumberText.setGravity(Gravity.CENTER);
pointNameText = new TextView(getActivity());
pointNameText.setTextSize(18);
pointNameText.setTextColor(getResources().getColor(R.color.grey_users_label));
pointNameText.setTypeface(avenirLight);
pointNameText.setText(metricName);
pointNameText.setGravity(Gravity.CENTER);
pointDateText = new TextView(getActivity());
pointDateText.setTextSize(11);
pointDateText.setTextColor(getResources().getColor(R.color.grey_users_label));
pointDateText.setTypeface(avenirHeavy);
pointDateText.setGravity(Gravity.CENTER);
pointInfoConatiner.addView(pointNumberText, 0, layoutParams);
layoutParams.setMargins(0, 2, 0, 0);
pointInfoConatiner.addView(pointNameText, 1, layoutParams);
pointInfoConatiner.addView(pointDateText, 2, layoutParams);
point = new ImageView(getActivity());
point.setImageDrawable(getResources().getDrawable(R.drawable.puntoon));
}
}
Anyone know how can I:
1-Quit the bottom border
2-Quit the line of the pink chart
3-The chart don't move when I touch the points
4- When I ask for the screen point why to many times the y value returns infinite
There used to be this bug in an older version of AChartEngine. I suggest you update to 1.1.0.
Also, please note that the chart must have been already displayed when calling the method. If the chart didn't display on screen then there is no way to calculate that.
Related
I code a mini game for Android where an animal is controlled by the player when the player clicks on the sides of the Drawable.
I wonder if it is better, and if yes, how to make the Drawable touchable so that the player can drag the character to either side instead of clicking by its sides? I'm interested in both UX/UI opinion and actual solution to the problem.
package dev.android.jamie;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
Log.d("myTag", "This is my message" + parent.getItemAtPosition(pos));
String name = "Jamie";
String str = parent.getItemAtPosition(pos).toString();
if (str.equals("Rookie")) {
cg = new CatchGame(this, 3, name, onScoreListener);
// setContentView(cg);
mainLayout.addView(cg);
getSupportActionBar().hide();
setContentView(mainLayout);
Log.d("game", "Started Rookie game");
} else if (str.equals("Advanced")) {
mainLayout = new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout menuLayout = new LinearLayout(this);
menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));
textView = new TextView(this);
textView.setVisibility(View.VISIBLE);
str = "Score: 0";
textView.setText(str);
menuLayout.addView(textView);
Button button = new Button(this);
button.setText("Pause");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
togglePausePlay();
}
});
menuLayout.addView(button);
Spinner spinner2 = new Spinner(this);
spinner2.setOnItemSelectedListener(this);
ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
spinner2.setAdapter(adapter);
menuLayout.addView(spinner2);
mainLayout.addView(menuLayout);
cg = new CatchGame(this, 5, "Jamie", onScoreListener);
cg.setBackground(getResources().getDrawable(R.drawable.bg_land_mdpi));
mainLayout.addView(cg);
// getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
getSupportActionBar().hide();
setContentView(mainLayout);
Log.d("game", "Started Advanced game");
} else if (str.equals("Expert")) {
cg = new CatchGame(this, 7, name, onScoreListener);
//setContentView(cg);
mainLayout.addView(cg);
getSupportActionBar().hide();
setContentView(mainLayout);
}
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
CatchGame cg;
public TextView textView;
public LinearLayout mainLayout;
String[] spinnerValue = {"Difficulty", "Rookie", "Advanced", "Expert", "Master"};
// start app
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainLayout = new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout menuLayout = new LinearLayout(this);
menuLayout.setBackgroundColor(Color.parseColor("#FFFFFF"));
textView = new TextView(this);
textView.setVisibility(View.VISIBLE);
String str = "Score: 0";
textView.setText(str);
menuLayout.addView(textView);
Button button = new Button(this);
button.setText("Pause");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
togglePausePlay();
}
});
menuLayout.addView(button);
Spinner spinner2 = new Spinner(this);
spinner2.setOnItemSelectedListener(this);
ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, spinnerValue);
spinner2.setAdapter(adapter);
menuLayout.addView(spinner2);
mainLayout.addView(menuLayout);
cg = new CatchGame(this, 5, "Jamie", onScoreListener);
cg.setBackground(getResources().getDrawable(R.drawable.bg_land_mdpi));
mainLayout.addView(cg);
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
getSupportActionBar().hide();
setContentView(mainLayout);
}
private void togglePausePlay() {
if (cg.paused) {
// play
// getSupportActionBar().hide();
Toast.makeText(MainActivity.this, "Play", Toast.LENGTH_SHORT).show();
} else {
// pause
// getSupportActionBar().show();
Toast.makeText(MainActivity.this, "Pause", Toast.LENGTH_SHORT).show();
}
cg.paused = !cg.paused;
}
private OnScoreListener onScoreListener = new OnScoreListener() {
#Override
public void onScore(int score) {
textView.setText("Score: " + score);
}
};
interface OnScoreListener {
void onScore(int score);
}
class CatchGame extends View {
int NBRSTEPS; // number of discrete positions in the x-dimension; must be uneven
String heroName;
int screenW;
int screenH;
int[] x; // x-coordinates for falling objects
int[] y; // y-coordinates for falling objects
int[] hero_positions; // x-coordinates for hero
Random random = new Random();
int ballW; // width of each falling object
int ballH; // height of ditto
float dY; //vertical speed
Bitmap falling, hero, jamie2, jamieleft, jamieright, falling2;
int heroXCoord;
int heroYCoord;
int xsteps;
int score;
int offset;
boolean gameOver; // default value is false
boolean toastDisplayed;
boolean paused = false;
OnScoreListener onScoreListener;
// constructor, load images and get sizes
public CatchGame(Context context, int difficulty, String name, OnScoreListener onScoreListener) {
super(context);
NBRSTEPS = difficulty;
heroName = name;
this.onScoreListener = onScoreListener;
x = new int[NBRSTEPS];
y = new int[NBRSTEPS];
hero_positions = new int[NBRSTEPS];
int resourceIdFalling = 0;
int resourceIdFalling2 = 0;
int resourceIdHero = 0;
if (heroName.equals("Jamie")) {
resourceIdFalling = R.mipmap.falling_object2;
resourceIdFalling2 = R.drawable.coconut_hdpi;
resourceIdHero = R.drawable.left_side_hdpi;
setBackground(getResources().getDrawable(R.mipmap.background));
}
falling = BitmapFactory.decodeResource(getResources(), resourceIdFalling); //load a falling image
falling2 = BitmapFactory.decodeResource(getResources(), resourceIdFalling2); //load a falling image
hero = BitmapFactory.decodeResource(getResources(), resourceIdHero); //load a hero image
jamieleft = BitmapFactory.decodeResource(getResources(), R.drawable.left_side_hdpi); //load a hero image
jamieright = BitmapFactory.decodeResource(getResources(), R.drawable.right_side_hdpi); //load a hero image
ballW = falling.getWidth();
ballH = falling.getHeight();
}
// set coordinates, etc.
void initialize() {
if (!gameOver) { // run only once, when the game is first started
int maxOffset = (NBRSTEPS - 1) / 2;
for (int i = 0; i < x.length; i++) {
int origin = (screenW / 2) + xsteps * (i - maxOffset);
x[i] = origin - (ballW / 2);
hero_positions[i] = origin - hero.getWidth();
}
int heroWidth = hero.getWidth();
int heroHeight = hero.getHeight();
hero = Bitmap.createScaledBitmap(hero, heroWidth * 2, heroHeight * 2, true);
hero = Bitmap.createScaledBitmap(hero, heroWidth * 2, heroHeight * 2, true);
jamieleft = Bitmap.createScaledBitmap(jamieleft, jamieleft.getWidth() * 2, jamieright.getWidth() * 2, true);
jamieright = Bitmap.createScaledBitmap(jamieright, jamieright.getWidth() * 2, jamieright.getWidth() * 2, true);
heroYCoord = screenH - 2 * heroHeight; // bottom of screen
}
for (int i = 0; i < y.length; i++) {
y[i] = -random.nextInt(1000); // place items randomly in vertical direction
}
offset = (NBRSTEPS - 1) / 2; // place hero at centre of the screen
heroXCoord = hero_positions[offset];
// initialize or reset global attributes
dY = 2.0f;
score = 0;
gameOver = false;
toastDisplayed = false;
}
// method called when the screen opens
#Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenW = w;
screenH = h;
xsteps = w / NBRSTEPS;
initialize();
}
// method called when the "game over" toast has finished displaying
void restart(Canvas canvas) {
toastDisplayed = true;
initialize();
draw(canvas);
}
// update the canvas in order to display the game action
#Override
public void onDraw(Canvas canvas) {
if (toastDisplayed) {
restart(canvas);
return;
}
super.onDraw(canvas);
int heroHeight = hero.getHeight();
int heroWidth = hero.getWidth();
int heroCentre = heroXCoord + heroWidth / 2;
Context context = this.getContext();
// compute locations of falling objects
for (int i = 0; i < y.length; i++) {
if (!paused) {
y[i] += (int) dY;
}
// if falling object hits bottom of screen
if (y[i] > (screenH - ballH) && !gameOver) {
dY = 0;
gameOver = true;
paused = true;
int duration = Toast.LENGTH_SHORT;
final Toast toast = Toast.makeText(context, "GAME OVER!\nScore: " + score, duration);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
toast.cancel();
toastDisplayed = true;
}
}, 3000);
//Vibrator v = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
// Vibrate for 3000 milliseconds
//v.vibrate(3000);
}
// if the hero catches a falling object
if (x[i] < heroCentre && x[i] + ballW > heroCentre &&
y[i] > screenH - ballH - heroHeight) {
y[i] = -random.nextInt(1000); // reset to new vertical position
score += 1;
onScoreListener.onScore(score);
}
}
canvas.save(); //Save the position of the canvas.
for (int i = 0; i < y.length; i++) {
if (i % 2 == 0)
canvas.drawBitmap(falling2, x[i], y[i], null); //Draw the falling on the canvas.
else
canvas.drawBitmap(falling, x[i], y[i], null); //Draw the falling on the canvas.
}
canvas.drawBitmap(hero, heroXCoord, heroYCoord, null); //Draw the hero on the canvas.
canvas.restore();
//Call the next frame.
invalidate();
}
// event listener for when the user touches the screen
#Override
public boolean onTouchEvent(MotionEvent event) {
if (paused) {
paused = false;
}
int action = MotionEventCompat.getActionMasked(event);
if (action != MotionEvent.ACTION_DOWN || gameOver) { // non-touchdown event or gameover
return true; // do nothing
}
int coordX = (int) event.getX();
int xCentre = (screenW / 2) - (hero.getWidth() / 2);
int maxOffset = hero_positions.length - 1; // can't move outside right edge of screen
int minOffset = 0; // ditto left edge of screen
if (coordX < xCentre && offset > minOffset) { // touch event left of the centre of screen
offset--; // move hero to the left
if (coordX < heroXCoord)// + heroWidth / 2)
hero = Bitmap.createScaledBitmap(jamieleft, jamieleft.getWidth(), jamieleft.getHeight(), true);
}
if (coordX > xCentre && offset < maxOffset) { // touch event right of the centre of screen
offset++; // move hero to the right
if (coordX > heroXCoord)
hero = Bitmap.createScaledBitmap(jamieright, jamieright.getWidth(), jamieright.getHeight(), true);
}
heroXCoord = hero_positions[offset];
return true;
}
}
}
I have a graph built using androidplot. I need to see each value horizontally (rotate 90 degrees). In the screenshot I showed what I mean. How to do it?
There is not a configuration option built in to do this, but it'd relatively easy to do in a custom renderer. Here's the quickstart example modified to do it:
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.androidplot.ui.SeriesRenderer;
import com.androidplot.util.PixelUtils;
import com.androidplot.xy.CatmullRomInterpolator;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.LineAndPointRenderer;
import com.androidplot.xy.PointLabelFormatter;
import com.androidplot.xy.PointLabeler;
import com.androidplot.xy.SimpleXYSeries;
import com.androidplot.xy.XYGraphWidget;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeries;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.List;
/**
* A simple XYPlot
*/
public class SimpleXYPlotActivity extends Activity {
private XYPlot plot;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_xy_plot_example);
// initialize our XYPlot reference:
plot = (XYPlot) findViewById(R.id.plot);
// create a couple arrays of y-values to plot:
final Number[] domainLabels = {1, 2, 3, 6, 7, 8, 9, 10, 13, 14};
Number[] series1Numbers = {1, 4, 2, 8, 4, 16, 8, 32, 16, 64};
Number[] series2Numbers = {5, 2, 10, 5, 20, 10, 40, 20, 80, 40};
// turn the above arrays into XYSeries':
// (Y_VALS_ONLY means use the element index as the x value)
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series1");
XYSeries series2 = new SimpleXYSeries(
Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
// create formatters to use for drawing a series using LineAndPointRenderer
// and configure them from xml:
LineAndPointFormatter series1Format =
new MyLineAndPointFormatter(this, R.xml.line_point_formatter_with_labels);
LineAndPointFormatter series2Format =
new MyLineAndPointFormatter(this, R.xml.line_point_formatter_with_labels_2);
// add an "dash" effect to the series2 line:
series2Format.getLinePaint().setPathEffect(new DashPathEffect(new float[] {
// always use DP when specifying pixel sizes, to keep things consistent across devices:
PixelUtils.dpToPix(20),
PixelUtils.dpToPix(15)}, 0));
// (optional) add some smoothing to the lines:
// see: http://androidplot.com/smooth-curves-and-androidplot/
series1Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
series2Format.setInterpolationParams(
new CatmullRomInterpolator.Params(10, CatmullRomInterpolator.Type.Centripetal));
// add a new series' to the xyplot:
plot.addSeries(series1, series1Format);
plot.addSeries(series2, series2Format);
plot.getGraph().getLineLabelStyle(XYGraphWidget.Edge.BOTTOM).setFormat(new Format() {
#Override
public StringBuffer format(Object obj, #NonNull StringBuffer toAppendTo, #NonNull FieldPosition pos) {
int i = Math.round(((Number) obj).floatValue());
return toAppendTo.append(domainLabels[i]);
}
#Override
public Object parseObject(String source, #NonNull ParsePosition pos) {
return null;
}
});
}
/**
* A LineAndPointRenderer that rotates it's point labels -90 degrees.
*/
static class MyLineAndPointRenderer extends LineAndPointRenderer<MyLineAndPointFormatter> {
public MyLineAndPointRenderer(XYPlot plot) {
super(plot);
}
// Basically just copy the entire renderPoints implementation and add a rotation as shown below
#Override
protected void renderPoints(Canvas canvas, RectF plotArea, XYSeries series, int iStart, int iEnd, List<PointF> points,
LineAndPointFormatter formatter) {
if (formatter.hasVertexPaint() || formatter.hasPointLabelFormatter()) {
final Paint vertexPaint = formatter.hasVertexPaint() ? formatter.getVertexPaint() : null;
final boolean hasPointLabelFormatter = formatter.hasPointLabelFormatter();
final PointLabelFormatter plf = hasPointLabelFormatter ? formatter.getPointLabelFormatter() : null;
final PointLabeler pointLabeler = hasPointLabelFormatter ? formatter.getPointLabeler() : null;
for(int i = iStart; i < iEnd; i++) {
PointF p = points.get(i);
if(p != null) {
if (vertexPaint != null) {
canvas.drawPoint(p.x, p.y, vertexPaint);
}
if (pointLabeler != null) {
// this is where we rotate the text:
final int canvasState = canvas.save();
try {
canvas.rotate(-90, p.x, p.y);
canvas.drawText(pointLabeler.getLabel(series, i),
p.x + plf.hOffset, p.y + plf.vOffset, plf.getTextPaint());
} finally {
canvas.restoreToCount(canvasState);
}
}
}
}
}
}
}
static class MyLineAndPointFormatter extends LineAndPointFormatter {
// if you dont use configurator you can omit this constructor. this example uses it
// tho so here it is.
public MyLineAndPointFormatter(Context context, int xmlCfgId) {
super(context, xmlCfgId);
}
#Override
public Class<? extends SeriesRenderer> getRendererClass() {
return MyLineAndPointRenderer.class;
}
#Override
public SeriesRenderer doGetRendererInstance(XYPlot plot) {
return new MyLineAndPointRenderer(plot);
}
}
}
The important stuff is at the bottom in MyLineAndPointRenderer. Basically you're just extending LineAndPointRenderer and overriding renderPoints(...) to rotate the canvas -90 degrees before drawing the text labels, and then restore the canvas immediately after.
I'm trying to make small App. This App have Activity, Custom View Class, and service.
1) Activity ask service for new Data and redraw Custom view
2) Service is listning to Bluetooth device and parse data.
Everything was fine, but I noticed that App is slowing down after 40 mins working.
I made another project remove service and find that it slowing too! So problem is my Customview class, maybe i have memory leaks in service to... but i have problem with drawings 100%.
I found that i have some objects that i'm creating on onDraw() method.. i try to move all thise staff to onSizeChanged() - but get more lags.
And now i need help. I need some example with simple drawings that depends on device width and height (I think my method is wrong - i use proportions of my 'Design' to calculate demetions in px)
By the way i'm using animator which make animations more smooth))
public class Dynamics {
/**
* Used to compare floats, if the difference is smaller than this, they are
* considered equal
*/
private static final float TOLERANCE = 0.01f;
/** The position the dynamics should to be at */
private float targetPosition;
/** The current position of the dynamics */
private float position;
/** The current velocity of the dynamics */
private float velocity;
/** The time the last update happened */
private long lastTime;
/** The amount of springiness that the dynamics has */
private float springiness;
/** The damping that the dynamics has */
private double damping;
public Dynamics(float springiness, float dampingRatio) {
this.springiness = springiness;
this.damping = dampingRatio * 2 * Math.sqrt(springiness);
}
public void setPosition(float position, long now) {
this.position = position;
lastTime = now;
}
public void setVelocity(float velocity, long now) {
this.velocity = velocity;
lastTime = now;
}
public void setTargetPosition(float targetPosition, long now) {
this.targetPosition = targetPosition;
lastTime = now;
}
public void update(long now) {
float dt = Math.min(now - lastTime, 50) / 1000f;
float x = position - targetPosition;
double acceleration = -springiness * x - damping * velocity;
velocity += acceleration * dt;
position += velocity * dt;
lastTime = now;
}
public boolean isAtRest() {
final boolean standingStill = Math.abs(velocity) < TOLERANCE;
final boolean isAtTarget = (targetPosition - position) < TOLERANCE;
return standingStill && isAtTarget;
}
public float getPosition() {
return position;
}
public float getTargetPos() {
return targetPosition;
}
public float getVelocity() {
return velocity;
}
}
In my Custom view i have this to set new data:
public void SetData(int[] NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now = AnimationUtils.currentAnimationTimeMillis();
if (datapoints == null || datapoints.length != newDatapoints.length) {
datapoints = new Dynamics[newDatapoints.length];
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i] = new Dynamics(70f, 0.50f);
datapoints[i].setPosition(newDatapoints[i], now);
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
invalidate();
} else {
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
removeCallbacks(animator);
post(animator);
}
LastData=NewData;
//redraw();
}
Thise is "code" of my custom view, after all changes it's look terible, so i cut 90% of it. And i make some test code insted:
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AnimationUtils;
import java.io.IOException;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Random;
public class CustomDisplayView extends View {
//paint for drawing custom view
private Paint RectPaint = new Paint();
//Динамические данные float
private Dynamics[] datapoints;
//Динамические статические Int
private int[] NewData = new int[500];
//созадем новый объект квадрат
private RectF rectf= new RectF();
//Задаем массив динамических цветов
int[] CurColors= new int[100];
int[] TargetColors= new int[100];
public CustomDisplayView(Context context, AttributeSet attrs){
super(context, attrs);
//Установка парметров красок
RectPaint.setAntiAlias(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != 0 && h != 0) {
//create Bitmap here
}
}
/**
* Override the onDraw method to specify custom view appearance using canvas
*/
#Override
protected void onDraw(Canvas canvas) {
//Get Screen size
//int viewWidth=this.getMeasuredWidth();
// int viewHeight = this.getMeasuredHeight();
//Выводим код цвета
RectPaint.setColor(0xff000000);
RectPaint.setTextSize(40);
canvas.restore();
canvas.drawText("V: " + datapoints[1].getPosition(), 20, 60, RectPaint);
//int saveCount = canvas.save();
for(int a=0;a<1000;a++)
{
rectf.set(datapoints[a].getPosition(), datapoints[a + 1].getPosition(), datapoints[a].getPosition() + datapoints[a + 1].getPosition() / 10, datapoints[a + 1].getPosition() + datapoints[a + 1].getPosition() / 10);
RectPaint.setColor(0x88005020);
//RectPaint.setColor(CurColor[a]);
//canvas.rotate(datapoints[1].getPosition(), viewWidth/2, viewHeight/2);
canvas.drawRoundRect(rectf, 0, 0, RectPaint);
//canvas.restore();
}
//canvas.restoreToCount(saveCount);
/*
for(int a=0;a<999;a++)
{
CurColors[a]=progressiveColor(CurColors[a], TargetColors[a], 2);
if(CurColors[a]==TargetColors[a])
{
TargetColors[a]=randomColor();
}
}
*/
canvas.restore();
}
//Рандом колор
public static int randomColor(){
Random random = new Random();
int[] ColorParams= new int[4];
ColorParams[0]=random.nextInt(235)+20;
ColorParams[1]=random.nextInt(255);
ColorParams[2]=random.nextInt(255);
ColorParams[3]=random.nextInt(255);
return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
}
//Интерполяция цвета
public static int progressiveColor(int CurColor,int TargetColor,int Step){
//Current color
int[] ColorParams= new int[4];
ColorParams[0]=(CurColor >> 24) & 0xFF;
ColorParams[1]=(CurColor >> 16) & 0xFF;
ColorParams[2]=(CurColor >> 8) & 0xFF;
ColorParams[3]=CurColor & 0xFF;
//TargetColor
int[] TargetColorParams= new int[4];
TargetColorParams[0]=(TargetColor >> 24) & 0xFF;
TargetColorParams[1]=(TargetColor >> 16) & 0xFF;
TargetColorParams[2]=(TargetColor >> 8) & 0xFF;
TargetColorParams[3]=TargetColor & 0xFF;
for(int i=0;i<4;i++)
{
if(ColorParams[i]<TargetColorParams[i])
{
ColorParams[i]+=Step;
if(ColorParams[i]>TargetColorParams[i])
{
ColorParams[i]=TargetColorParams[i];
}
}
else if(ColorParams[i]>TargetColorParams[i])
{
ColorParams[i]-=Step;
if(ColorParams[i]<TargetColorParams[i])
{
ColorParams[i]=TargetColorParams[i];
}
}
}
//int red = r - (int)((float)(r*255)/(float)all);
//int green = (int)((float)(g*255)/(float)all);
return Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3]);
//return String.format("#%06X", (0xFFFFFF & Color.argb(ColorParams[0], ColorParams[1], ColorParams[2], ColorParams[3])));
//return " "+opacity+" "+red+" "+green+" "+blue;
}
//each custom attribute should have a get and set method
//this allows updating these properties in Java
//we call these in the main Activity class
/**
* Get the current text label color
* #return color as an int
*/
public int getLabelColor(){
return 1;
}
/**
* Set the label color
* #param newColor new color as an int
*/
public void setLabelColor(int newColor){
//update the instance variable
//labelCol=newColor;
//redraw the view
invalidate();
requestLayout();
}
public void redraw(){
//redraw the view
invalidate();
requestLayout();
}
public void SetData(int[] NewData2,float[]newDatapoints)
{
this.NewData=NewData2;
long now = AnimationUtils.currentAnimationTimeMillis();
if (datapoints == null || datapoints.length != newDatapoints.length) {
datapoints = new Dynamics[newDatapoints.length];
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i] = new Dynamics(70f, 0.50f);
datapoints[i].setPosition(newDatapoints[i], now);
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
invalidate();
} else {
for (int i = 0; i < newDatapoints.length; i++) {
datapoints[i].setTargetPosition(newDatapoints[i], now);
}
removeCallbacks(animator);
post(animator);
}
//redraw();
}
public int GetAction(float x,float y)
{
/*
if(x>(DicsCenterX-LineHalfSpeedZone) && x<(DicsCenterX+LineHalfSpeedZone) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
{
// private int SpeedZoneRadius2=0;
// private int PowerOutRadius=0;
//Смена режима
//начинаем смену размеру index / ms
ChangeVal(0,700);
return 1;
}
else if(x>(CofCantBGDrop*2) && x<(CofCantBGDrop*4) && y>(DicsCenterY-PowerOutRadius) && y<(DicsCenterY-SpeedZoneRadius2))
{
return 2;
}
else
{
return 0;
}
//return 0;
*/
return 1;
}
public static String fmt(double d)
{
double val = d/100;
String result;
if(val == (long) val)
result= String.format("%d",(long)d);
else
result= String.format("%s",d);
if(result.length()<2)
{
String result2=result;
result="0"+result2;
}
return result;
}
private Runnable animator = new Runnable() {
#Override
public void run() {
boolean needNewFrame = false;
long now = AnimationUtils.currentAnimationTimeMillis();
for (Dynamics dynamics : datapoints) {
dynamics.update(now);
if (!dynamics.isAtRest()) {
needNewFrame = true;
}
}
if (needNewFrame) {
postDelayed(this, 15);
}
invalidate();
}
};
}
I just want to understand where i need to declare scale values, where i need to calc real dimensions in px.. and et.c. to have no memory leaks..
If i remove color change and incrice number of Rects up to 1000 - i get lags.
All methods o any information how to debug memory leaks - you are wellcome!
You have to remove runnable for animation when view is detached.
if (needNewFrame) {
postDelayed(this, 15); <--- memory leak
}
Try like this.
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallback(your runnable);
}
Also refreshing every 15 milliseconds is very heavy.
I have the following class which generates a calendar view. I'm not too fond of the built-in one, and am trying to gain more control over its appearance. However rendering the new UI (e.g. upon swipe) is taking 1-2 seconds to draw. Is there any place I could speed this up? Am testing on HTC One S (2012 model)
Should be relatively straightforward to follow:
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import org.joda.time.LocalDate;
import java.util.ArrayList;
public class Calendar extends AppCompatActivity {
private LocalDate _currentSelectedDate = new LocalDate();;
private LocalDate _today = new LocalDate();;
private float x1 = 0;
private float x2 = 0;
private float y1 = 0;
private float y2 = 0;
private TableLayout _tableLayout;
private RelativeLayout _relativeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calendar);
_relativeLayout = (RelativeLayout) findViewById(R.id.calendarLayout);
recreateUI(_currentSelectedDate.getYear(), _currentSelectedDate.getMonthOfYear());
}
#Override
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
case MotionEvent.ACTION_DOWN:
{
x1 = touchevent.getX();
y1 = touchevent.getY();
break;
}
case MotionEvent.ACTION_UP:
{
x2 = touchevent.getX();
y2 = touchevent.getY();
// up
if (y1 > y2)
{
_currentSelectedDate = _currentSelectedDate.plusMonths(1);
recreateUI(_currentSelectedDate.getYear(), _currentSelectedDate.getMonthOfYear());
}
// down
if (y1 < y2)
{
_currentSelectedDate = _currentSelectedDate.minusMonths(1);
recreateUI(_currentSelectedDate.getYear(), _currentSelectedDate.getMonthOfYear());
}
break;
}
}
return false;
}
private void recreateUI(int year, int month)
{
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
_tableLayout = new TableLayout(this);
_tableLayout.setLayoutParams(lp);
_tableLayout.setStretchAllColumns(true);
_relativeLayout.removeAllViews();
_relativeLayout.addView(_tableLayout);
LocalDate date = new LocalDate().withYear(year).withMonthOfYear(month).dayOfMonth().withMinimumValue();
LocalDate last = date.dayOfMonth().withMaximumValue();
addMonthNameToUi(date);
addDaysNamesToUi();
addDayNumberssToUi(date, last);
}
private void addMonthNameToUi(LocalDate date) {
TableRow row = new TableRow(this);
TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.FILL_PARENT);
params.span = 7;
TextView t = new TextView(this);
t.setLayoutParams(params);
t.setGravity(Gravity.CENTER);
t.setTypeface(null, Typeface.BOLD);
t.setText(date.toString("MMM yyyy"));
row.addView(t);
float d = getResources().getDisplayMetrics().density;
int margin = (int)(20 * d);
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) t.getLayoutParams();
mlp.setMargins(mlp.leftMargin, mlp.topMargin, mlp.rightMargin, margin);
_tableLayout.addView(row);
}
private void addDaysNamesToUi() {
TableRow dayNameRow = new TableRow(this);
addMonth(dayNameRow, "Mon");
addMonth(dayNameRow, "Tue");
addMonth(dayNameRow, "Wed");
addMonth(dayNameRow, "Thu");
addMonth(dayNameRow, "Fri");
addMonth(dayNameRow, "Sat");
addMonth(dayNameRow, "Sun");
_tableLayout.addView(dayNameRow);
}
private void addDayNumberssToUi(LocalDate date, LocalDate last) {
TableRow row = null;
int columnsCount = 0;
boolean firstRow = true;
while (date.isBefore(last) || date.isEqual(last)) {
if (columnsCount == 0) {
row = new TableRow(this);
_tableLayout.addView(row, new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.FILL_PARENT, 1.0f));
// blank columns for days not at the start of month
if (firstRow) {
firstRow = false;
int i = 1;
for (; i < date.getDayOfWeek(); i++) {
addDayNumberToRow(row, date, "");
}
columnsCount += i - 1;
date.plusDays(i - 1);
}
}
addDayNumberToRow(row, date, String.valueOf(date.getDayOfMonth()));
date = date.plusDays(1);
columnsCount++;
if (columnsCount == 7)
columnsCount = 0;
}
while (row.getChildCount() < 7)
addDayNumberToRow(row, date, "");
}
private void addMonth(TableRow row, String month)
{
TextView t = new TextView(this);
t.setText(month);
t.setGravity(Gravity.CENTER);
t.setTypeface(null, Typeface.BOLD);
row.addView(t);
}
private void addDayNumberToRow(TableRow row, final LocalDate date, String text)
{
TextView v = new TextView(this);
v.setText(text);
v.setGravity(Gravity.CENTER);
v.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.FILL_PARENT, 1.0f));
if (date.getDayOfMonth() == _today.getDayOfMonth() && date.getMonthOfYear() == _today.getMonthOfYear() && date.getYear() == _today.getYear()) {
v.setTypeface(v.getTypeface(), Typeface.BOLD);
v.setTextSize(v.getTextSize() + 1);
}
ShapeDrawable border = new ShapeDrawable(new RectShape());
border.getPaint().setStyle(Paint.Style.STROKE);
border.getPaint().setColor(Color.BLACK);
v.setBackground(border);
row.addView(v);
}
}
Your "recreateUI" method do alot of stuff like creating new views. Avoid creating new objects by reusing those already created.
Usually calendar views are quite complex. You most likely wont achieve smooth framerate by using multiple views in such way. You would have to write custom view witch will draw itself.
Turns out a lot of the slowdown was caused from running the application under debug mode -- running it normally resulted in acceptable performance.
I have a spinner and it has items 1,2,3 and so on.And on selection of a particular item in spinner edittexts should appear dynamically depending on the number from spinner.
If i select 3 from the drop down, i am getting three edittexts dynamically but once again if i select 2 its not displaying 2 edittexts...kindly help me to resolve.
I have attached my code..
package com.example.spinner;
import static android.view.ViewGroup.LayoutParams.FILL_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.widget.LinearLayout.VERTICAL;
import java.util.ArrayList;
import java.util.List;
import android.R.integer;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Spinner;
public class spin_activity extends Activity {
private Spinner sp;
EditText et1, et2;
List<String> list;
RelativeLayout rl;
boolean isspinnerselected = false;
private List<EditText> editTextList = new ArrayList<EditText>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spinner);
rl = (RelativeLayout) findViewById(R.id.r1);
System.out.println("####################################");
setitem();
}
private void setitem() {
/*
* sp =(Spinner)findViewById(R.id.spinner1);
*
*
*
* ArrayAdapter<CharSequence> data =
* ArrayAdapter.createFromResource(getApplicationContext(),
* R.array.Fruits, android.R.layout.simple_spinner_item);
* data.setDropDownViewResource
* (android.R.layout.simple_spinner_dropdown_item); sp.setAdapter(data);
* sp.setOnItemSelectedListener(this);
*/
sp = (Spinner) findViewById(R.id.spinner1);
list = new ArrayList<String>();
list.add("How many kids?");
list.add("1");
list.add("2");
list.add("3");
list.add("4");
ArrayAdapter<String> adp = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line, list);
adp.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
sp.setAdapter(adp);
System.out.println("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
sp.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int pos,
long id) {
System.out.println("positoin" + pos);
if (isspinnerselected) {
final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
(int) LayoutParams.WRAP_CONTENT,
(int) LayoutParams.WRAP_CONTENT);
// et1.setFocusable(true);
params.leftMargin = 80;
params.topMargin = 100;
System.out.println("Spinner selected");
int val = Integer.parseInt(sp.getSelectedItem().toString());
System.out.println("value of val" + val);
System.out.println("Child count: " + rl.getChildCount());
if (rl.getChildCount() >1 ) {
System.out.println("*************");
rl.removeViews(1, rl.getChildCount()-2);
System.out.println("Aft removng child, count is: "
+ rl.getChildCount());
}
for (int i = 0; i < val; i++)
{
System.out.println("value of i: " + i);
System.out.println("BEFORE>>>>>>Params top margin: "
+ params.topMargin);
et1 = new EditText(spin_activity.this);
et1.setFocusable(true);
et1.setLayoutParams(params);
et1.setHint("EditText" + params.topMargin);
et1.setBackgroundColor(Color.GREEN);
// et1.setLayoutParams(new
// RelativeLayout.LayoutParams(source))
rl.addView(et1);
System.out.println("Child count aft adding et: "
+ rl.getChildCount());
params.topMargin += 100;
System.out.println("AFTER>>>>>>Params top margin: "
+ params.topMargin);
}
} else
System.out.println("Spinner selected is false");
isspinnerselected = true;
/*
* et2 = new EditText (spin_activity.this);
* RelativeLayout.LayoutParams _params = new
* RelativeLayout.LayoutParams ((int) LayoutParams.WRAP_CONTENT,
* (int) LayoutParams.WRAP_CONTENT); et2.setFocusable(true);
* _params.leftMargin = 80; _params.topMargin = 280;
* et2.setLayoutParams(_params); et2.setHint("EditText");
* et2.setEms(10); rl.addView(et2);
*/
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
/*
* #Override public void onItemSelected(AdapterView<?> parent, View arg1,
* int pos, long arg3) { System.out.println("positoin"+pos);
*
* if(pos==0) { EditText et1 = new EditText (this);
* RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
* ((int) LayoutParams.WRAP_CONTENT, (int) LayoutParams.WRAP_CONTENT);
*
* params.leftMargin = 80; params.topMargin = 180;
* et1.setLayoutParams(params); et1.setHint("EditText"); et1.setEms(10); }
*
* if(pos==1) { editText("name"); }
*
*
* switch (pos) { case 0: EditText et1 = new EditText (this);
*
* RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
* ((int) LayoutParams.WRAP_CONTENT, (int) LayoutParams.WRAP_CONTENT);
*
* params.leftMargin = 80; params.topMargin = 180;
*
* et1.setLayoutParams(params);
*
* et1.setHint("EditText"); et1.setEms(10);
*
*
* break; case 1: // What ever you want to happen when item selected break;
* case 2: // What ever you want to happen when item selected break;
*
* }
*
* } private EditText editText(String hint) { EditText editText = new
* EditText(this); editText.setId(Integer.valueOf(hint));
* editText.setHint(hint); editTextList.add(editText); return editText; }
*
* #Override public void onNothingSelected(AdapterView<?> arg0) { // TODO
* Auto-generated method stub
*
* }
*/
}