Android Studio: exchange data between classes - java

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.

Related

NullPointerException after setting variable of own view object class

I am playing a bit around with java and kotlin at the moment.
I wanted to have a custom view class which shall be part of my main activity. Therefore I let my class "MyGridView" inherit from View and added some methods.
I then created an MyGridView object (myGrid) in my MainActivity and call the "setPlayTable(playTable)" method, which sets the playTable variable of the object myGrid to playTable. When I later want to use this variable I get a null pointer reference. When debugging I can clearly see, how myGrid's playTable variable is set. But when later called, I get the NullPointerException. Here are the important parts of my code:
Class MyGridView
public class MyGridView extends View {
private HashMap<Integer, Integer> playTable;
public MyGridView(Context context) {
this(context, null);
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
blackPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
public void setPlayTable(HashMap<Integer, Integer> playTable){
this.playTable = playTable;
}
public void drawPlayTable(Canvas canvas){
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(42);
this.setNumColumns(10);
this.setNumRows(10);
for(int x = 0; x < 10; x++){
for(int y = 0; y < 10; y++){
int posX = (int)((x+0.5)*cellWidth);
int posY = (int)((x+1)*cellHeight);
Log.d("playtable",this.playTable.toString());
canvas.drawText(Integer.toString(this.playTable.get(10*x+y)), posX, posY, paint);
}
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawPlayTable(canvas);
}
MainActivity (kotlin)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
rollDice()
val indexes = (1..100).toList()
var numbers = indexes.shuffled()
playTable = HashMap<Int,Int>(indexes.zip(numbers).toMap())
var myGrid = MyGridView(this)
myGrid.setNumColumns(10)
myGrid.setNumRows(10)
myGrid.setPlayTable(playTable)
myGrid.invalidate()
when I call the "invalidate" method, the onDraw() method is called, which calls the drawPlayTable() method. in there I get the Exception as soon as I try to access the playTable variable.
Why does this happen? Did I by accident set the class instead of the object variable? Please help me to solve this issue :D

Null pointer exception when using multiple fragment that uses a custom seek bar

I have a custom Seek bar that that i made following a tutorial on the net. Here is the code for the CustomSeekBar class.
public class CustomSeekBar extends SeekBar {
private ArrayList<ProgressItem> mProgressItemsList;
public CustomSeekBar(Context context) {
super(context);
}
public CustomSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void initData(ArrayList<ProgressItem> progressItemsList) {
this.mProgressItemsList = progressItemsList;
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
protected void onDraw(Canvas canvas) {
if (mProgressItemsList.size() > 0) {
int progressBarWidth = getWidth();
int progressBarHeight = getHeight();
int thumboffset = getThumbOffset();
int lastProgressX = 0;
int progressItemWidth, progressItemRight;
for (int i = 0; i < mProgressItemsList.size(); i++) {
ProgressItem progressItem = mProgressItemsList.get(i);
Paint progressPaint = new Paint();
progressPaint.setColor(getResources().getColor(
progressItem.color));
progressItemWidth = (int) (progressItem.progressItemPercentage
* progressBarWidth / 100);
progressItemRight = lastProgressX + progressItemWidth;
// for last item give right to progress item to the width
if (i == mProgressItemsList.size() - 1
&& progressItemRight != progressBarWidth) {
progressItemRight = progressBarWidth;
}
Rect progressRect = new Rect();
progressRect.set(lastProgressX, thumboffset / 2,
progressItemRight, progressBarHeight - thumboffset / 2);
canvas.drawRect(progressRect, progressPaint);
lastProgressX = progressItemRight;
}
super.onDraw(canvas);
}
}
}
I have used this custom widget in a fragment. This fragment has multiple instance of this custom widget.
The fragment is used in multiple activities. There is an activity where the fragment works fine but in another activity where i try to use two of the above fragments i get a NullPointer Exception.
From the stacktrace i can trace the null pointer exception back to the line
if (mProgressItemsList.size() > 0) {
The strange thing is that when i add the fragment to only one framelayout the code works fine. But when i add the fragment to another framelayout in the same activity i get this null pointer exception. I am confused on what is causing this and am wondering what is the best way to tackle this?
The problem was that i was working with the view in the views of my fragment onActivityCreated() method. If you are planning to use the same fragment twice in any activity this is a very bad idea. I had two fragments initialized but only a single fragment and its views was initialized because i was using getActivity().findViewById() .
The solution to this is to work with your fragment's view on onViewCreated(View view, #Nullable Bundle savedInstanceState) and instead of using getActivity().findViewById() using view.findViewById().

Java classes List not updating from List in another class

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

Accessing the members of a simple class in Android

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.

Custom View Scrolling issues Android

I've been designing an application that requires the use of a scrollbar on a custom view. The problem that I have run into is that my custom view's height will constantly change when new items are added by the user. I suspect that this isn't a very unusual problem, but to complicate things, I'm not actually adding new objects to my custom view, I'm just drawing Bitmap images on the canvas. The reason this is troublesome to me is when Android inflates the layout, it sets the size to be whatever I tell it (0dip) and as I add the Bitmaps, it simply changes the size to fill the Scrollview; thereby, whenever the Custom View draws an image beyond the current height constraints, instead of scrolling, the app simply cuts the picture off to maintain the current height.
(This is for a card game app, so I wanted to fan out your current deck in a easy to view and edit fashion.)
Here is the relevant code :
public class DeckEdit extends Activity implements FilterQueryProvider {
static final int PROGRESS_DIALOG = 0;
private Deck deck;
private CardListAdapter lstAdpt;
private ArrayList<CardImage> cards;
private ProgressDialog progressDialog;
private ProgressThread progressThread;
private String[] cardList;
private DeckEditCardView deckGrid;
private ScrollView sc;
protected Cursor cursor;
private EditText filterText = null;
ArrayAdapter<String> adapter = null;
public void onCreate(Bundle savedInstanceBundle){
super.onCreate(savedInstanceBundle);
deck = new Deck();
//This is what stores the Card Images that I draw to the canvas with
cards = new ArrayList<CardImage>();
setContentView(R.layout.deck_edit_layout);
sc = (ScrollView) findViewById(R.id.deck_scroller);
deckGrid = (DeckEditCardView) findViewById(R.id.deck_grid);
filterText = (EditText) findViewById(R.id.card_search_box);
filterText.addTextChangedListener(filterTextWatcher);
pickDeck();
}
And then this is called after I load the deck
private void finishSetup(){
//this is where I set up the deckGrid to have all the cards and then
deckGrid.setCards(cards);
//draw them to the screen
deckGrid.invalidate();
//This is where I realized that the height value might be causing the problem
Log.d("finishSetup()", "deckGrid width: "+deckGrid.getWidth());
Log.d("finishSetup()", "deckGrid height: "+deckGrid.getHeight());
}
The DeckEditCardView class contains this
public class DeckEditCardView extends View implements OnTouchListener {
private ArrayList<CardImage> cards;
private int X_COLS;
#SuppressWarnings("unused")
private int Y_ROWS;
private final int COL_WIDTH;
private final int ROW_HEIGHT;
private Context context;
private final int X_PADDING = 2;
private final int Y_PADDING = 2;
private final int X_CARD_OVERLAY = 7;
private final int Y_CARD_OVERLAY = 5;
public DeckEditCardView(Context context) {
super(context);
cards = new ArrayList<CardImage>();
int cardWidth = getResources().getDrawable(R.drawable.back).getIntrinsicWidth();
int cardHeight = getResources().getDrawable(R.drawable.back).getIntrinsicHeight();
COL_WIDTH = (X_PADDING+(X_CARD_OVERLAY*3)+cardWidth);
Log.d("DECV","COLWIDTH 1: "+COL_WIDTH);
ROW_HEIGHT = (Y_PADDING+(Y_CARD_OVERLAY*3)+cardHeight);
Log.d("DECV","ROWE_HEIGHT 1: "+ROW_HEIGHT);
}
public DeckEditCardView(Context context, AttributeSet attrs) {
super(context, attrs);
cards = new ArrayList<CardImage>();
int cardWidth = getResources().getDrawable(R.drawable.back).getIntrinsicWidth();
int cardHeight = getResources().getDrawable(R.drawable.back).getIntrinsicHeight();
COL_WIDTH = (X_PADDING+(X_CARD_OVERLAY*3)+cardWidth);
Log.d("DECV","COLWIDTH 2 : "+COL_WIDTH);
ROW_HEIGHT = (Y_PADDING+(Y_CARD_OVERLAY*3)+cardHeight);
Log.d("DECV","ROWE_HEIGHT 2: "+ROW_HEIGHT);
}
/*
public DeckEditCardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
cards = new ArrayList<CardImage>();
int width = getWidth();
int height = getHeight();
int cardWidth = getResources().getDrawable(R.drawable.back).getIntrinsicWidth();
int cardHeight = getResources().getDrawable(R.drawable.back).getIntrinsicHeight();
COL_WIDTH = (X_PADDING+(X_CARD_OVERLAY*3)+cardWidth);
Log.d("DECV","COLWIDTH 3: "+COL_WIDTH);
ROW_HEIGHT = (Y_PADDING+(Y_CARD_OVERLAY*3)+cardHeight);
Log.d("DECV","ROWE_HEIGHT 3: "+ROW_HEIGHT);
X_COLS = (width/COL_WIDTH);
Y_ROWS = (height/ROW_HEIGHT);
}
*/
#Override
public void onFinishInflate(){
super.onFinishInflate();
//this.
}
public void onSizeChanged(int w, int h, int oldw, int oldh){
int width = getWidth();
int height = getHeight();
X_COLS = (width/COL_WIDTH);
Y_ROWS = (height/ROW_HEIGHT);
}
public Point getNextCardPoint(Point curP, boolean sameCard){
Point p=null;
if (sameCard)
p = new Point(curP.x+X_CARD_OVERLAY,curP.y+Y_CARD_OVERLAY);
else { //need to be on the same column
if (point2Col(curP)+1<X_COLS)
p = new Point(COL_WIDTH*(point2Col(curP)+1)+X_PADDING,
ROW_HEIGHT*(point2Row(curP))+Y_PADDING);
else {//add to new column
if (point2Row(curP)+1 > Y_ROWS)
Y_ROWS++;
p = new Point(X_PADDING,
ROW_HEIGHT*(point2Row(curP)+1)+Y_PADDING);
}
}
return p;
}
public void setCards(ArrayList<CardImage> cards){
this.cards = cards;
}
private int point2Col(Point p){
return p.x / COL_WIDTH;
}
private int point2Row(Point p){
return p.y / ROW_HEIGHT;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//ScrollView s = new ScrollView(context);
//s.addView(canvas);
int length = cards.size();
CardImage c;
for (int i = 0; i < length; i++) {
//Log.d("onDraw", "output a card");
c = cards.get(i);
canvas.drawBitmap(c.getBitmap(), c.getX(), c.getY(), null);
}
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}
So in conclusion, I don't know how to allow the user to scroll and see the cards that don't fit on the screen (its almost guaranteed that a fully built deck will take a scrollbar to see all of them. At most with this code it'll put in all the card images I need, but the ones that go of screen I don't know what to do :/
And lastly my Layout.xml file
<com.xeroxchange.ydd.DeckEditCardView android:layout_weight="2"
android:id="#+id/deck_grid"
android:layout_width="fill_parent"
android:layout_height="0dip"></com.xeroxchange.ydd.DeckEditCardView>
</ScrollView>
<LinearLayout android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!-- Pretty hint text, and maxLines -->
<EditText android:id="#+id/card_search_box"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="type to filter"
android:inputType="text"
android:maxLines="1"/>
<!-- Set height to 0, and let the weight param expand it -->
<!-- Note the use of the default ID! This lets us use a
ListActivity still! -->
<ListView android:id="#+id/card_list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="2"
/>
</LinearLayout>
</LinearLayout>
Your layout doesn't work properly because the DeckEditCardView doesn't measure itself. You must override the View.onMeasure() method in the DeckEditCardView class and set measured size depending on view's content. In your layout xml file you must specify wrap_content as a height of the DeckEditCardView.

Categories

Resources