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
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 would like to learn how to exchange data between classes(in Android Studio).
For that purpose I have created three Java classes:
1) GraficActivity.java:
public class GraficActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView iv = (ImageView) findViewById(R.id.testview);
//not working: iv.update(100,100);
DataHolder.setData(100, 100);
}
}
2) DrawingView.java:
public class DrawingView extends ImageView {
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
private int X=200;
private int Y=200;
//not working: X = DataHolder.getX();
//not working: Y = DataHolder.getY();
public void update(int dataX, int dataY) {
X=dataX;
Y=dataY;
this.invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint pinsel = new Paint();
pinsel.setColor(Color.rgb(64, 64, 255));
pinsel.setStrokeWidth(5);
canvas.drawLine(0, 0, X, Y, pinsel);
}
}
3) DataHolder.java:
public class DataHolder {
private static int X;
private static int Y;
public static int getX() {return X;}
public static int getY() {return Y;}
public static void setData(int dataX, int dataY) {X = dataX; Y=dataY;}
}
I included DrawingView in the layout (together with other elements) with the following code in main.xml:
<de.carpelibrum.grafik.DrawingView
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#ffffff"
android:id="#+id/testview" />
The app works in principle, but I could not find a way to transfer data from GraficActivity to DrawingView.
I tried two methods(as indicated in the code above):
Via a separate DataHolder as global variable
With the function update(int, int) in DrawingView.
Finally, I will need to transfer not only two integers, but the content of an array: int data[][];.
How to solve the problem?
Thank you in advance for your suggestions.
Cheers,
Kyriakos.
ImageView does not have a method update(int, int). You should cast the View associated with the id R.id.testView to your type DrawingView. Then update(int, int) should become available at compile-time:
DrawingView iv = (DrawingView) findViewById(R.id.testview);
Also, consider that your DataHolder and DrawingView are both storing position data. Pick one. If the data is specific to an instance of DrawingView, then you don't need DataHolder.
perfect! Thank you.
Regarding the database, I put it in "GraficActivity", sratched "DataHolder", and used a pointer as parameter in the "update" function:
in "GraficActivity":
private int data[][]=new int[10][10];
data[0][0] = 200;
data[0][1] = 100;
iv.update(data);
in "DrawingView":
public void update(int[][] dataXY) {
X=dataXY[0][0];
Y=dataXY[0][1];
this.invalidate();
}
Now this is a good working basis.
Cheers,
Kyriakos.
I'm an Android newbie developer and having an issue with a tiny Android app I'm developing which I suspect is related to timing of dynamic view creation. It's a little scorekeeper app and it has dynamically generated player buttons and text fields, defined in a Player class. Here's an excerpt of how I'm doing this:
public Player(String name, int score, int number, boolean enabled, RelativeLayout mainScreen, List<Button> presetButtonList, Editor editor, Context context) {
super();
this.name = name;
this.score = score;
this.number = number;
this.enabled = enabled;
this.editor = editor;
// Get the lowest child on the mainScreen
Integer count = mainScreen.getChildCount(), lowestChildId = null;
Float lowestChildBottom = null;
for (int i = 0; i < count; i++) {
View child = mainScreen.getChildAt(i);
if ((lowestChildId == null || child.getY() > lowestChildBottom) &&
!presetButtonList.contains(child)) {
lowestChildId = child.getId();
lowestChildBottom = child.getY();
}
}
playerNameText = (EditText) setTextViewDefaults(new EditText(context), name);
playerNameText.setSingleLine();
// playerNameText.setMaxWidth(mainScreen.getWidth());
// playerNameText.setEllipsize(TextUtils.TruncateAt.END); //TODO: Prevent names which are too long for screen
playerNameText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable changedText) {
setName(changedText.toString());
updateScreen();
}
public void beforeTextChanged(CharSequence changedText, int start, int count, int after) {}
public void onTextChanged(CharSequence changedText, int start, int before, int count) {}
});
RLParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
if (lowestChildId != null) {
RLParams.addRule(RelativeLayout.BELOW, lowestChildId);
} else {
RLParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
RLParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
}
RLParams.setMargins(0, 10, 0, 10);
mainScreen.addView(playerNameText, RLParams);
the class further defines buttons and etc in a similar fashion, aligning tops with the name text view. I call this when a user clicks a button to add a player, and it works fine, displaying each player below the first on down the screen. The problem comes in when I'm loading a bunch of saved players at the start. Here's where i load the players:
public void loadData() {
RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
playerCount = savedData.getInt("playerCount", playerCount);
Player player;
String name;
playerList.clear();
for (int i=1; i<=playerCount; i++) {
name = savedData.getString("name" + i, null);
if (name != null) {
Log.v("name", name);
player = new Player(name, savedData.getInt("score" + i, 0), i, savedData.getBoolean("enabled" + i, false), mainScreen, presetButtonList, editor, this);
playerList.add(player);
player.updateScreen();
}
}
updateScreen();
}
Finally, I call the loadData() method when the app starts, here:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
savedData = this.getPreferences(Context.MODE_PRIVATE);
editor = savedData.edit();
presetButtonList.add((Button)findViewById(R.id.newGame));
presetButtonList.add((Button)findViewById(R.id.addPlayer));
presetButtonList.add((Button)findViewById(R.id.removePlayer));
loadData();
}
The result? When there are more than two players to load, all the players get loaded to the same spot, on top of Player 2.
I suspect somehow that the players are all being generated at the same time and thus all believing that the lowest player view is Player 1, and not checking each other. I've tried triggering the load later than onCreate() and it still happens. I also tried adding a 3 second sleep within the for loop of loadData() after each player loads to see if that helped, but no luck.
Am I making bad assumptions? What am I doing wrong and how might I fix it?
I suspect what is happening here is that you are attempting to position views that don't have IDs (it looks like you don't set them anywhere in your code). Dynamically created views don't automatically have IDs, so a call to getId() will return NO_ID (See documentation). If you want to use an ID you will have to set it yourself using View.setId().
It was a timing issue after all. I needed to wait for the main screen to load before I could add views to it. Unfortunately, it would never load until all activity on the UI thread was finished.
Thus, I needed threading. I ended up putting loadData() in a thread, like this:
new Thread(new loadDataAsync(this)).start();
class loadDataAsync implements Runnable {
MainActivity mainActivity;
public loadDataAsync(MainActivity mainActivity) {
this.mainActivity = mainActivity;
}
#Override
public void run() {
try {
Thread.sleep(700);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
loadData(mainActivity);
}
}
Then I created the players back on the UI thread after the initial sleep to give time for the UI to load.
runOnUiThread(new Runnable() {
Player player;
RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
#Override
public void run() {
player = new Player(savedData.getString("name" + playerNum, null), savedData.getInt("score" + playerNum, 0), playerNum, savedData.getBoolean("enabled" + playerNum, false), mainScreen, presetButtonList, editor, mainActivity);
playerList.add(player);
player.updateScreen();
mainScreen.invalidate();
}
});
Not the most elegant solution, but it works for now.
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.