suppose imgv is an ImageView
if I say float x = imgv.getPivotX(); float y = imgv.getPivotY();
this will give me the pivot point, however, this requires your app to target api 11 and above, I want to do the same for api 8, what function should I use?
Pivot is related to animations. To make them compatible with Android 1.0+ you should use NineOldAndroids
Then you can use the helper class: float x = ViewHelper.getPivotX(imgv);
Related
I'm an experienced native iOS developer making my first foray into Android through Unity. I'm trying to set up a custom shader, but I'm having some trouble with the Normal maps. I've got them working perfectly in the Unity simulator on my computer, but when I build to an actual device (Samsung Galaxy S8+), the Normal maps don't work at all.
I'm using Mars as my test case. Here's the model running in the simulator on my computer:
And here's a screenshot from my device, running exactly the same code.
I've done a LOT of research, and apparently using Normal maps on Android with Unity is not an easy thing. There are a lot of people asking about it, but almost every answer I've found has said the trick is to override the texture import settings, and force it to be "Truecolor" which seems to be "RGBA 32 Bit" according to Unity's documentation. This hasn't helped me, though.
Another thread suggested reducing the Asino Level to zero, and another suggested turning off Mip Maps. I don't know what either of those are, but neither helped.
Here's my shader code, simplified but containing all references to Normal mapping:
void surf (Input IN, inout SurfaceOutputStandard o) {
half4 d = tex2D (_MainTex , IN.uv_MainTex);
half4 n = tex2D (_BumpMap , IN.uv_BumpMap);
o.Albedo = d.rgb;
o.Normal = UnpackNormal(n);
o.Metallic = 0.0;
o.Smoothness = 0.0;
}
I've seen some threads suggesting replacements for the "UnpackNormal()" function in the shader code, indicating that it might not be the thing to do on Android or mobile in general, but none of the suggested replacements have changed anything for better or worse: the normal maps continue to work in the simulator, but not on the device.
I've even tried making my own normal maps programmatically from a grayscale heightmap, to try to circumvent any import settings I may have done wrong. Here's the code I used, and again it works in the simulator but not on the device.
public Texture2D NormalMap(Texture2D source, float strength = 10.0f) {
Texture2D normalTexture;
float xLeft;
float xRight;
float yUp;
float yDown;
float yDelta;
float xDelta;
normalTexture = new Texture2D (source.width, source.height, TextureFormat.RGBA32, false, true);
for (int y=0; y<source.height; y++) {
for (int x=0; x<source.width; x++) {
xLeft = source.GetPixel (x - 1, y).grayscale * strength;
xRight = source.GetPixel (x + 1, y).grayscale * strength;
yUp = source.GetPixel (x, y - 1).grayscale * strength;
yDown = source.GetPixel (x, y + 1).grayscale * strength;
xDelta = ((xLeft - xRight) + 1) * 0.5f;
yDelta = ((yUp - yDown) + 1) * 0.5f;
normalTexture.SetPixel(x,y,new Color(xDelta,yDelta,1.0f,yDelta));
}
}
normalTexture.Apply();
return normalTexture;
}
Lastly, in the Build Settings, I've got the Platform set to Android and I've tried it using Texture Compression set to both "Don't Override" and "ETC (default)". The former was the original setting and the latter seemed to be Unity's suggestion both by the name and in the documentation.
I'm sure there's just some flag I haven't checked or some switch I haven't flipped, but I can't for the life of me figure out what I'm doing wrong here, or why there would be such a stubborn difference between the simulator and the device.
Can anyone help a Unity newbie out, and show me how these damn Normal maps are supposed to work on Android?
Check under:
Edit -> Project Settings -> Quality
Android is usually set to Fastest.
How can I create circular list for round watch as in android wear 2.0 ?.
Like this:
Circular list is seen in android wear app launcher.
First of all you need to replace your ListView with a WearableRecyclerView.
It can be used like a normal ListView. But make sure, you import the right one from android.support.wear.widget. DON'T use the one from android.support.wearable.view. This one should be crossed out, so it won't take you long to check if you're using the right one. If there's just one WearableRecyclerViewto choose from, make sure to add compile 'com.android.support:wear:27.0.0' to the dependencies in your build.gradle (wear) file.
Also make sure that you're using <android.support.wear.widget.WearableRecyclerView/> in your activity.xml. If you just want a circular ListView without any custom item-scaling, just call this in your onLayoutInflated() method:
your_recyclerview.setEdgeItemsCenteringEnabled(true);
your_recyclerview.setLayoutManager(new WearableLinearLayoutManager(your_activity_context));
If you want to make items scaling up when they get closer to the center of your screen, things get a little more complicated.
First: paste this in your Activity.java:
private class CustomScrollingLayoutCallback extends WearableLinearLayoutManager.LayoutCallback {
private static final float MAX_ICON_PROGRESS = 2F;
#Override
public void onLayoutFinished(View child, RecyclerView parent) {
float centerOffset = ((float) child.getHeight() / 2.0f) / (float) parent.getHeight();
float yRelativeToCenterOffset = (child.getY() / parent.getHeight()) + centerOffset;
float progresstoCenter = (float) Math.sin(yRelativeToCenterOffset * Math.PI);
float mProgressToCenter = Math.abs(0.5f - yRelativeToCenterOffset);
mProgressToCenter = Math.min(mProgressToCenter, MAX_ICON_PROGRESS);
child.setScaleX(1 - mProgressToCenter);
child.setScaleY(1 - mProgressToCenter);
child.setX(+(1 - progresstoCenter) * 100);
}
}
Then go back to your onLayoutInflated() method, and type the following:
CustomScrollingLayoutCallback customScrollingLayoutCallback = new CustomScrollingLayoutCallback();
your_recycler_view.setLayoutManager(new WearableLinearLayoutManager(your_context, customScrollingLayoutCallback));
your_recycler_view.setCircularScrollingGestureEnabled(true);
done.
This is now possible with Android Wear 2.0's WearableRecyclerView.
According to Android Developer Docs:
Wear 2.0 introduces the WearableRecyclerView class for displaying and
manipulating a vertical list of items optimized for round displays.
WearableRecyclerView extends the existing RecyclerView class to
provide a curved layout and a circular scrolling gesture in wearable
apps.
You may like to read more about Android Wear 2.0 Preview 3.
Was trying to implement the snippet below. [from developer documentation here]:
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
Gettting the error below. Why is it so and how can i fix this.
java.lang.NoClassDefFoundError: android.view.ViewAnimationUtils
at dejavu.appzonegroup.com.dejavuandroid.Fragment.PeopleTabFragment$1.onItemClick(PeopleTabFragment.java:59)
at android.widget.AdapterView.performItemClick(AdapterView.java:299)
at android.widget.AbsListView.performItemClick(AbsListView.java:1152)
ViewAnimationUtils was added in API level 21 (Lollipop 5.0). Are you testing your app on Lollipop? It will not work on older API levels. To use it you need to set min SDK to 21.
One google search brought me this, it gives you 3 ways to solve your problem. I'll quote a few wich I think that might resolve your problem:
1) Class is not available in Java Classpath.
2) You might be running your program using jar command and class was
not defined in manifest file's ClassPath attribute.
I recently updated my Android app (see source on Github) to use Android Studio 0.6.0, which required bumping the build-tools to v19.1.0 (from v19.0.1), the Android Gradle plugin to v0.11 (from 0.9), and the Gradle wrapper to 1.12 (from 1.11).
Before the above changes (at this commit), the app was successfully drawing squares on a canvas to show signal strength of GLONASS satellites (see IDs 87 and 88):
After updating my Android tools and launching via Android Studio or gradlew installDebug, the squares suddenly disappeared (see IDs 77, 87, 88):
The code that draws the square, with a center of (x,y), is:
canvas.drawRect(x - SAT_OFFSET, y + SAT_OFFSET, x + SAT_OFFSET, y - SAT_OFFSET, mSatelliteStrokePaint);
(see Github for full class)
The commit with all changes to update to Android Studio 0.6.0 can be seen here.
Why did canvas.drawRect() suddenly stop working after updating the Android tools?
Apparently this has something to do with Android handling invalid input values for drawRect(), triggered by Android Gradle Plugin 0.11 enabling the new manifest merging tool by default.
If I add useOldManifestMerger true to my build.gradle, then the squares return:
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
useOldManifestMerger true
...
}
The underlying problem was that Canvas.drawRect() takes in the parameters (float left, float top, float right, float bottom, Paint paint)
I had the top and bottom coordinates of the rectangle reversed, so the top value (which should have been the smallest y value) was the larger y value, and the bottom value (which should have been the largest y value) was the smallest y value (the origin (0,0) is in the upper left corner).
Before Android Studio 0.6.0 tool updates, Android was correcting invalid input and still drawing the square. After Android Studio 0.6.0 tool update started using the new manifest merging tool, Android is no longer correcting invalid input and instead it doesn't draw anything.
After changing my code to reverse the top/bottom y values of the square:
c.drawRect(x - SAT_OFFSET, y - SAT_OFFSET, x + SAT_OFFSET, y + SAT_OFFSET, mSatelliteStrokePaint);
...the squares reappeared (even when using the new manifest merger - i.e., without adding useOldManifestMerger true to build.gradle).
So, the correct way to fix this issue is to reverse the top/bottom coordinates of the square to be valid input, and still use the new manifest merger.
This is ridiculous - we have been 'drawing rectangles backwards' for over 30 years. There are valid programmatic reasons to draw backwards sometimes.
Use the following if you need this functionality.
public static void drawRectOriented(Canvas g, float x1,float y1,float x2,float y2,Paint p) {
if (x1 > x2) {
float t = x2;
x2 = x1;
x1 = t;
}
if (y1 > y2) {
float t = y2;
y2 = y1;
y1 = t;
}
g.drawRect(x1,y1,x2,y2, p);
}
I'm writing crossplatform application. It should run on Android devices.
I want to use dFdx/dFdy for antialiasing. But, unfortunately, glsl es 2.0 does not support derivatives.
Can I replace dFdx/dFdy with something? I.E. 1/sprite_width, 1/sprite_height in screen pixels.
As I said, I need this to work on android devices. And I saw that my device support GL_OES_standard_derivatives, which allow it to use this functions. Does all android opengl es 2.0 devices support it?
As I said many Opengl ES 2.0 devices support GL_OES_standard_derivatives extension.
But for thoose who don't, I made this workaround:
float myFunc(vec2 p){
return p.x*p.x - p.y; // that's our function. We want derivative from it.
}
// this calculated in vertex shader
// width/height = triangle/quad width/height in px;
vec2 pixel_step = vec2(1/width, 1/height);
float current = myFunc(texCoord);
float dfdx = myFunc(texCoord + pixel_step.x) - current;
float dfdy = myFunc(texCoord + pixel_step.y) - current;
float fwidth = abs(dx) + abs(dy); // from khronos doc #http://www.khronos.org/registry/gles/extensions/OES/OES_standard_derivatives.txt
P.S. I get very close results to the glsl built ins, A little bit more blurry (in my shader). To fix this I added multiply pixel_step on 1/1.75. If someone knows why, let me know.