I split my inner View class from my Main class into its own file. In my main class, I have the view set as an onTouchListener which records user movement into a matrix so it can translate and scale the view. After separating it everything works but im unsure how to pass the matrix to the View for onDraw to update. Any suggestions? Thanks
I can think of two ways to do this:
You could create a variable for your matrix in your View class and a method that accepts a matrix as argument and that updates the var with this matrix value. Then you can call this method from your main Activity before calling your onDraw() method, which can then use this internal var for its calculations and so on.
An alternative would be for your matrix var in your main class to be static so you can call it from your View without needing to have an instance of your main class accessible within your View class.
The latter method is the best as it doesn't require your app to maintain two vars with essentially the same value but the former method might be easier to implement, depending on how your matrix is calculated/implemented.
Related
I have one imageView animation, so when i rotate screen it start again. How do i use that with viewModel.
Here is code
lateinit var img = ImageView
img = findViewById(R.id.img)
Img.animate().translationY(600F).setDuration(2000).setStartDelay(2000)
ViewModel holds data, but it should not hold a reference to a View.
You could place a boolean in the ViewModel that is true, and after the animation you set its value to false. If you then turn your phone and the boolean value remains false, so it would not animate again.
You will have something like this:
img = findViewById(R.id.img);
if (vm.getBooleanValue()) {
img.animate().translationY(600F).setDuration(2000).setStartDelay(2000);
vm.setBooleanValue(false);
}
There are two ways you can solve this problem:
Use the viewmodel
Use onSaveInstanceState ()
Is. The second method is not suitable for heavy and large data and it is better to use the first method for your purpose.
viewmodels are not rebuilt when your UI is restarted, which is why you see the same UI as the previous UI in the output.
You can see how to implement viewmodels in Android by viewing the codelab below:
https://developer.android.com/codelabs/kotlin-android-training-view-model?index=..%2F..android-kotlin-fundamentals#4
You can read more information about viewmodels from the link below:
https://developer.android.com/topic/libraries/architecture/viewmodel
Cheers,
I have an app that receives user input (2 numbers, width and height) and in theory depending on that input I have a custom view that should draw a grid (width and height).
Note:
These 2 values should be received before view attempts to draw itself.
These 2 values aren't constant and therefore I don't think XML approach can help.
I was told that adding another parameter to the View constructor is evil.
Do not confuse my 2 values with canvas.getWidth or etc.. these are values needed simply to draw something, nothing else.
My View is also a ViewGroup.
Main issue arises with Views declared in XML files.
I have temporarily solved this issue by making an SchemeContext class which contains those 2 static values and I simply set them in onCreate (before onCreateView) then use them in custom View onDraw when needed (SchemeContext.width). This is not really what people would call OOP I'm forcing global variables upon java and those are set on time because of the fragment lifecycle.
I've seen this answer How to pass variables to custom View before onDraw() is called?.
But it's more of a workaround than a solution (and probably not the fastest one). There has to be a sensible solution I don't think 3D games on android resort to these workarounds (SurfaceView with OpenGL is still a View right? :d).
If there is an obvious solution and this is an obvious double I'll remove the question.
I haven't tried this, but I think it would be possible to do this fairly cleanly by overriding the LayoutInflater.Factory. That way, you can intercept the creation of the views that need additional parameters passed to their constructors, and let the rest of them fall through to default inflation.
For example, in your activity, before you inflate the view hierarchy:
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
MyInflaterFactory factory = new MyInflaterFactory();
// Pass information needed for custom view inflation to factory.
factory.setCustomValue(42);
inflater.setFactory(factory);
For your implementation of the factory:
class MyInflaterFactory implements LayoutInflater.Factory {
public void setCustomValue(int val) {
mCustomVal = val;
}
#Override
public View onCreateView (String name, Context context, AttributeSet attrs) {
if (name.equals("com.package.ViewWithCustomCreation")) {
return new ViewWithCustomCreation(context, attrs, mCustomVal);
}
return null;
}
private int mCustomVal;
}
I was told that adding another parameter to the View constructor is evil.
Nonsense.
There are three (and in the newest APIs, four) different View constructors, each used in a different situation. (See this thread.) If you wanted to be able to declare your view in XML, for example, then you'd have to provide a constructor with exactly the right parameters, and have it call the corresponding superclass constructor. But there's nothing wrong with defining your own constructor (or even several of them) that call the superclass constructor intended for creating views programmatically.
The overriding principle is that every object must be valid when its constructor returns. So unless you can provide reasonable default values in your constructor, you have little choice but to accept the object's properties as constructor parameters.
I'm fairly new to Java & Android, so I have little idea what I am doing.
My test program successfully creates view objects, so now I am trying to organize my code.
I want to make a separate class to manage my GUI, but it always fails.
Basic info about my gui class:
package horc.gui;
...
public class GUI{
private Context context;
From my main activity, I constructed that gui class with the app context.
gui=new GUI(getApplicationContext()); // gui is a var of type GUI, & this sets the context of the class
The problem is when I make/modify a view object that is in the class from outside, it throws an exception.
My main activity...
package horc.test;
...
GUI gui;
LinearLayout test=gui.newLinear("ff", "v"); // <-- this sets fill parent for width/height
// & vertical orientation of the vertical layout.
// Doesnt work for the reason stated above.
// I cannot manage any view objects from a separate class.
gui.lastText.setText("##########"); // <-- a variable in the class to hold the view object I am manipulating
setContentView(t);
...calls this class function:
public TextView newText(String text){
TextView test=new TextView(context);
lastLinear.addView(test);
return test;
}
I tested this similar body within the main activity & it worked fine. It only fails when I do anything from outside that gui class.
Is there a common issue that people run into when managing view objects in separate classes? I have absolutely no idea what I am doing at this point. Coming from C++, java seems like a nutty language. I cannot plan things the way I would in C++.
instead of
gui=new GUI(getApplicationContext());
try
gui=new GUI(MyActivity.this);
Please put your activity name instead of MyActivity
I want to know how a View is created in Android. On a View object creation which functions are called?Initially constructors will be called.Next what? And so on.
If anybody know the sequence of functions called after object creation,Please reply me.
Thanks
This might help you better I guess.
1) Constructor : to initialize variables
2) onMeansure : to prepare canvas , set Width and height
3)OnDraw() : to draw actual view .
now onDraw() will continuously be called after a particular interval which depends upon display/processor and UI eventsenter code here or on calling invalidate()
I'm writing an app for android and I have a class setup that extends View. Inside that class I'm overwriting onDraw.
I have another class where I'm doing a lot of the processing. I was wondering if there was a way I can use the onDraw method inside the 2nd class too? The 2nd class isn't extending anything.
You can instantiate the 2nd class from the first, then pass the Canvas you receive as parameter to the method of the 2nd witch need it.
Something like.
public void onDraw(Canvas canvas){
super.onDraw(canvas);
MyDrawer drawer = new MyDrawer(); //The 2nd class
canvas.store(); //Use it to store the actual matrix and any further change you can do in the paint method will not take effect over the original matrix
drawer.drawOn(canvas);
canvas.restore();//Return the original matrix, any new paint will use the original matrix
}