I have a simple Java class which extends View in another package, and I am making a custom view using this class. I want to use it as a View in XML from another class, which is an Activity.
My custom View needs some data from that class, so I created an object of Pt class, which extends Activity. The object is created, but when I am use that object for accessing the members of the class that extends Activity, it does not show any members. Am I doing something wrong, or there is a better way to do it?
Here is my code. I have shown what I am expecting within the comments.
public class PlotView extends View {//class to make a custom view
Plot_View obj_plot = new Plot_View();
obj_plot.// here i am expecting it to show the members of that Plot_View class which is extending Activity
class Pt{
float x, y;
Pt(float _x, float _y){
x = _x;
y = _y;
}
}
Pt[] myPath = { new Pt(100, 100), new Pt(200, 200), new Pt(200, 500),
new Pt(400, 500), new Pt(400, 200) };
public PlotView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public PlotView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
Path path = new Path();
path.moveTo(myPath[0].x, myPath[0].y);
for (int i = 1; i < myPath.length; i++){
path.lineTo(myPath[i].x, myPath[i].y);
}
canvas.drawPath(path, paint);
}
}//
and here is my Plot_View Activity .i want to access these Arraylists defined here in this activity
public class Plot_View extends Activity implements OnClickListener {
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.plotview);
calculationForPlot();
findViewById(R.id.btn_measure).setOnClickListener(this);
initMirrorMatrix();
drawMatrix();
}
private void calculationForPlot(){
ArrayList<String> al_edit_A_ft = new ArrayList<String>();
ArrayList<String> al_edit_A_inch=new ArrayList<String>();
ArrayList<String>al_edit_B_ft=new ArrayList<String>();
ArrayList<String>al_edit_B_inch= new ArrayList<String>();
float x=0;
AndroidOpenDbHelper androidOpenDbHelperObj = new AndroidOpenDbHelper(this);
SQLiteDatabase sqliteDatabase = androidOpenDbHelperObj.getReadableDatabase();
String q="SELECT * FROM ab_measurement WHERE job_id=" +"\""+Settings.jobid +"\"";
Cursor cursor = sqliteDatabase.rawQuery(q,null);
if (cursor.moveToNext()) {
System.out.println(cursor.getCount());
m=Integer.parseInt(cursor.getString(4));
do {
try{
float a = 0,b = 0;
a=(float) Double.parseDouble(cursor.getString(6));
String number =String.valueOf(a);
System.out.println("aaa ggg"+number);
String int_part =number.substring(0,number.indexOf("."));
String float_part=number.substring(number.lastIndexOf(".")+1,number.length());
System.out.println("aaa values"+int_part);
System.out.println("aaa values"+float_part);
al_edit_A_ft.add(int_part);
al_edit_A_inch.add(float_part);
b= (float) Double.parseDouble(cursor.getString(7));
String number_b =String.valueOf(b);
System.out.println("aaa ggg"+number_b);
String int_part_b =number_b.substring(0,number_b.indexOf("."));
String float_part_b=number_b.substring(number_b.lastIndexOf(".")+1,number_b.length());
System.out.println("aaa values"+int_part_b);
System.out.println("aaa values"+float_part_b);
al_edit_B_ft.add(int_part_b);
al_edit_B_inch.add(float_part_b);
x= (float) Double.parseDouble(cursor.getString(3));
String ft_base =String.valueOf(x);
System.out.println("aaa ggg"+ft_base);
String int_part_ft =ft_base.substring(0,ft_base.indexOf("."));
String float_part_inch=ft_base.substring(ft_base.lastIndexOf(".")+1,ft_base.length());
System.out.println("aaa values"+int_part_ft);
System.out.println("aaa values"+float_part_inch);
}
catch (Exception e) {
}
} while (cursor.moveToNext());
Try this....
Create an object reference variable of Your_Activity type in the Java class, and initialize it in the contructor with the Context passed to it.
Activity class:
public class MyActivity extends Activity {
TextView myView ;
protected void onCreate(android.os.Bundle savedInstanceState) {
myView = (TextView)findViewById(R.id.myView);
Points myPoints = new Points(this);
myPoints.displayMsg("MY NAME IS VIVEK");
}
}
Java class:
private class Points {
public MyActivity mcontext;
////---------- a constructor with the Context of your activity
public Points(MyActivity context){
mcontext = context;
}
public void displayMsg( final String msg){
context.runOnUiThread(new Runnable() {
#Override
public void run() {
mcontext.myView.setText(msg);
}
});
}
}
From the way your commented line of code is incomplete, I assume you are using an auto-complete feature of your IDE.
My first suggestion is to change the name Plot_View to PlotActivity. This will help you avoid confusion when you return to this project in the future. Also, it will help avoid confusion when you ask questions here.
As for your actualy question, I assume you are referring to the following ArrayLists:
ArrayList<String> al_edit_A_ft = new ArrayList<String>();
ArrayList<String> al_edit_A_inch=new ArrayList<String>();
ArrayList<String>al_edit_B_ft=new ArrayList<String>();
ArrayList<String>al_edit_B_inch= new ArrayList<String>();
First you need to realize that these are not members of the Plot_View class. They are declared locally in the calculationForPlot() method. Although, it appears that you have not posted the entire Plot_View class, so you may have declared other ArrayLists elsewhere. If you are indeed referring to the ArrayLists that I pasted above, you will need to declare them as member variables in Plot_View rather than as local variables in calculationForPlot(). Then you can create getter methods to allow your View class to access them.
Related
I'm having some trouble with an issue in my Android Studio application that is to do with pressing the back button. Basically the user inputs into a text view and another method (not included as it works fine but I can post if requested) searches an API for the relevant data and displays it in a recycler view. Then the user makes a selection from the recycler view and the method below parses a JSON file and adds relevant data from it to an array in a separate class "Director". Once this happens the next activity "GraphActivity" starts and draws a number of nodes on a canvas for each director in the array.
The issue I am having is that when I make an input into the text view and then press the back button to close the soft keyboard on my Android device (it covers up the recycler view) and go through the steps I just mentioned, when the GraphActivity activity starts it does not work (no nodes are drawn). However, if I then press the back button to go back to the first activity and then make the same selection from the recycler view again, it works.
From what I can tell, the issue seems to be with the data being added to the "Director" array but I cannot figure out what is causing it, Logcat shows that the first time the GraphActivity activity starts the "Director" array is empty and therefore, no nodes are drawn but when I press back and then make the same selection again the array has the correct data and the nodes are drawn.
I would really appreciate some help with this as I am very new to Android Studio and have been searching around for hours to try and find a solution.
public class MainActivity extends AppCompatActivity implements MainAdapter.OnCompanyClickedListener {
private RecyclerView recyclerView;
private TextView userInput;
private Button search;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.rView);
RecyclerView.LayoutManager manager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(manager);
}
//Parse JSON File
public void searchCompanyDirectors(final String companyNumber){
Thread thread = new Thread(new Runnable(){
#Override
public void run(){
HttpClient httpClient = new HttpClient();
try{
final String response = httpClient.run("myURL");
runOnUiThread(new Runnable(){
#Override
public void run(){
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray array = jsonObject.getJSONArray("items");
for (int i = 0; i < array.length();i++){
JSONObject o = array.getJSONObject(i);
String appointment = o.getString("links");
String parsedAppointment = parseApp(appointment);
Director director = new Director(o.getString("name"),parsedAppointment);
Director.directorList.add(director);
}
}catch (JSONException e){
e.printStackTrace();
}
}
});
}
catch (Exception ex){
ex.printStackTrace();
}
}
});
thread.start();
}
#Override
public void onCompanyClicked(int position) {
Toast.makeText(this,Company.companyList.get(position).getTitle(),Toast.LENGTH_LONG).show();
chosenCompanyNumber = Company.companyList.get(position).getCompanyNumber();
chosenCompany = Company.companyList.get(position).getTitle();
searchCompanyDirectors(chosenCompanyNumber);
Intent intent = new Intent(this,GraphActivity.class);
startActivity(intent);
}
}
The GraphActivity class:
public class GraphActivity extends AppCompatActivity {
DrawGraph drawGraph;
#SuppressLint("ClickableViewAccessibility")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawGraph = new DrawGraph(this);
setContentView(drawGraph);
The DrawGraph class:
public class DrawGraph extends View {
private Paint p1;
private Paint p2;
private Paint p3;
private Paint paint;
private Path path;
private Point point1;
private int radius = 300;
double x;
double y;
double angle;
int mWidth = this.getResources().getDisplayMetrics().widthPixels;
int mHeight = this.getResources().getDisplayMetrics().heightPixels;
List<Director> directorList = Director.getDirectorList();
private String chosenCompany = MainActivity.getChosenCompany();
private static List<Float> ordinates = new ArrayList<>();
public DrawGraph(Context context) {
super(context);
p1 = new Paint(Paint.ANTI_ALIAS_FLAG);
p1.setStrokeWidth(10);
p2 = new Paint(Paint.ANTI_ALIAS_FLAG);
p2.setStrokeWidth(10);
p3 = new Paint(Paint.ANTI_ALIAS_FLAG);
p3.setStrokeWidth(5);
path = new Path();
paint = new Paint();
point1 = new Point(mWidth/2, mHeight/2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Colors
p1.setStyle(Paint.Style.FILL);
p1.setColor(Color.RED);
p2.setStyle(Paint.Style.FILL);
p2.setColor(Color.GREEN);
p3.setStyle(Paint.Style.STROKE);
p3.setColor(Color.CYAN);
paint.setColor(Color.BLACK);
paint.setTextSize(18f);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.CENTER);
Rect bounds = new Rect();
paint.getTextBounds(chosenCompany, 0, chosenCompany.length(),bounds);
//Draw company and directors
for (int i = 1; i <= directorList.size(); i++)
{
//Divide the company node
angle = i * (360/directorList.size());
x = point1.x + radius * cos(angle);
y = point1.y + radius * sin(angle);
//Draw directors
canvas.drawCircle((float)x,(float)y - (bounds.height() / 2), bounds.width() + 5,p2);
canvas.drawText(directorList.get(i-1).getName(),(float)x,(float)y,paint);
}
Okay, I've found an issue in DrawGraph class noted here;
List<Director> directorList = Director.getDirectorList();
private String chosenCompany = MainActivity.getChosenCompany();
You should not directly access the data objects of one activity from another. The previous activity could be destroyed etc as per Android OS and its lifecycle. You must think of it like out of sight, out of memory; which can cause the current activity to not be able to access the data in the previous one.
You'd need to properly send the parsed data from your JSON file, the variables List directorList and the String chosenCompany from your MainActivity to GraphActivity.
You can send data from one activity to another by adding it to the intent with which you call the next activity. The Intent class has features to help you send a small amount of information via itself; called putExtra() and getExtra(). More about them here.
You will need to add those variable datasets through intent.putExtra and fetch them back in your other activity onCreate by using getExtras.
Activity A >> Intent call to Activity B + Data >> Activity B
Hope this helps.
I'm trying to get a random Base from an ArrayList:
Edit: full code:
public class MainActivity extends AppCompatActivity {
private Random randomGenerator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ArrayList<Base> baseArrayList = new ArrayList<Base>();
Base baseOne = new Base("Grüner Salat");
Base baseTwo = new Base("Gemischter Salat");
Base baseThree = new Base("Rüeblisalat");
Base baseFour = new Base("Eisbergsalat");
baseArrayList.add(baseOne);
baseArrayList.add(baseTwo);
baseArrayList.add(baseThree);
baseArrayList.add(baseFour);
Button mixSaladBtn = (Button) findViewById(R.id.mixSaladBtn);
mixSaladBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TextView baseTextView = (TextView) findViewById(R.id.baseTextView);
String baseDisplay = getRandomBase(baseArrayList);
baseTextView.setText(baseDisplay);
}
});
ArrayList<Ingredient> ingredientArrayList = new ArrayList<Ingredient>();
}
public String getRandomBase(ArrayList<Base> baseArrayList){
int index = randomGenerator.nextInt(baseArrayList.size());
Base randomBase = baseArrayList.get(index);
System.out.println(randomBase);
return randomBase.getIngredientName();
}
}
The App crashes when I call the method getRandomBase in the onClick method. Somehow I'm not getting back a Base from baseArrayList.get(index);
Final edit: I had 2 errors. The first one was that at first I used a raw type. Many thanks for the clarifications!
The second error was that I had to move the declaration of the Random randomGenerator();
You problem is in the method you are sending raw arraylist . so it doesn't know what data type it is . There are two ways you can fix
1. Casting
Base randomBase = (Base) baseArrayList.get(index);
Sending Type in method
public String getRandomBase(List<Base> baseArrayList){
}
Try
public String getRandomBase(ArrayList<Base> baseArrayList){...
I've got 2 activities and a class that extends Application where I'm trying to store global variables with a kind of setter getter functions.
The main activity sets some views and a chart; then calls the second activity which should be setting values to be used afterwards on the previous chart.
Then pressing backbutton and returning to the previous activity onRestart is called and the chart is refreshed.
The problem is I lose my theorically global variables somewhere. Debugging i realized that the functions work perfectly fine while im adding values in the second activity but when I return to the first activity globalXCount returns '0' again. Why is that?
I think im missunderstanding some point regarding lifecycles.
I attach some fragments of the code.
First activity:
public class MainActivity extends Activity {
Global glObj = new Global();
CombinedChart mChart;
private int itemcount;
float displayed;
private final List<String> mMonthList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itemcount = ((Global) this.getApplication()).getGlobalXCount();
displayed = itemcount/20;
mChart = (CombinedChart) findViewById(R.id.mchart);
populateHeaderList();
setChartSettings();
Intent intent = new Intent(MainActivity.this, QandA.class);
startActivity(intent);
}
#Override
protected void onRestart() {
super.onRestart();
itemcount = ((Global) this.getApplication()).getGlobalXCount();
displayed = itemcount/20;
populateHeaderList();
setChartSettings();
}
Second activity:
public class QandA extends Activity {
Global glObj = new Global();
ViewFlipper flipper;
private float lastX;
...
}else{
//TODO If all information if correctly filled
trainedmins = et1.getText().toString();
localLineValue = Integer.parseInt(trainedmins) * Integer.parseInt(statusQ1);
//Add values to lines
glObj.setLineXvalues(localLineValue);
// TODO Add new Bar value //
//Add 1 more value to count
glObj.addGlobalXCount();
}
...
Global class:
public class Global extends Application {
//TODO
public Integer globalXCount;
private List<Integer> lineXvalues = new ArrayList<>();
private List<Integer> barXvalues = new ArrayList<>();
//////
public Integer getGlobalXCount() {
if (this.globalXCount == null){
this.globalXCount = 0;
return this.globalXCount;
}else{
return this.globalXCount;
}
}
public void addGlobalXCount() {
if (this.globalXCount == null){
this.globalXCount = 0;
}else{
this.globalXCount = this.globalXCount + 1;
}
}
Thanks in advance.
First of all, register your custom Application context in AndroidManifest.xml within the <application>-tag.
<application
android:name="<your_package>.Global" ...>
Access the global application context within your activities like this:
Global glObj = (Global) getApplicationContext();
glObj.addGlobalXCount();
Do not create a new instance with new! Always retrieve the instance via getApplicationContext().
Furthermore, I would suggest you to initialize your class field glObj within the onCreate()-method of your Activities.
I do believe that answer should already be somewhere on so, but after some search I still cant figure out my problem..
public class cl1{
private List<Map> world_map = new ArrayList<Map>();
public List<Map> returnmap(){
return world_map;
}
public void addtomap(float x, float y, int type){
Map tile = new Map();
tile.x = x;
tile.y = y;
tile.type = type;
world_map.add(tile);
}
}
Activity class:
protected void onCreate(Bundle savedInstanceState) {
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View vw) {
List<Map> map = new ArrayList<Map>();
map = robot.returnmap();
for(int i=0;i<map.size();i++){
txt.setText(String.valueOf(i));
}
cl1.addtomap(x, y, 1);
x++;
y++;
}
This works fine: I can add to cl1.world_map with my method from activity class, and I can also get values from world_map from my activity class.
I have another class:
protected List<Map> strap = new ArrayList<Map>();
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
returnmap();
canvas.drawText(String.valueOf(strap.size()), 100, 120, paint1);
}
private void returnmap(){
strap = robot.returnmap();
}
Here I'm always getting value of 0, like the "List strap" would never update?
Your 'robot' variable is probably getting re-instantiated or is not even the same instance in your two classes, if that is not the case, keep in mind that in android there are many events under which you could get your fragments or activities re-instantiated and you should always save the state you intend to keep yourself
I am trying to call the view from another class in my Asynctask class but it doesn't seem to be working.
Here is my AsyncTack
private class parseSite extends AsyncTask<String, Void, List<Integer>> {
protected List<Integer> doInBackground(String... arg) {
List<Integer> output = new ArrayList<Integer>();
try {
htmlHelper hh = new htmlHelper(new URL(arg[0]));
output = hh.htmlHelper(arg[0]);
} catch (Exception e) {
System.out.println("Error");
}
return output;
}
protected void onPostExecute(List<Integer> exe) {
graph salesView = new graph();
View chartView = salesView.getView(this);
chartView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT, 1f));
LinearLayout layout = (LinearLayout) findViewById(R.id.linearview);
layout.addView(chartView, 0);
}
}
And here is what the activity 'graph' looks like
public class graph {
public View getView(Context context) (...etc.)
I don't understand why it can't call the view.
Assuming you intended graph to extend Context in some way, such as by extending Activity, and that parseSite is defined inside graph, make the following change:
View chartView = salesView.getView(graph.this);
In the original code, this is referring to parseSite which does not extend Context (and does not refer to graph as you probably intend).
As a side note, in typical Java style classes should be named with an upper case letter, i.e. Graph not graph.
I think the problem is that you try to access view from other thread that created it. Usual way is to use runOnUiThread():
(activity).runOnUiThread(new Runnable() {
public void run() {
//call anything to your View objects
}
});