Here is my code to translate imageview in X direction(from left to right).
final Animation animTrans = new TranslateAnimation(0f, 1f, 0f, 0f);
animTrans.setRepeatCount(0);
animTrans.setDuration(200);
animTrans.setFillAfter(true);
circleImage.startAnimation(animTrans);
When it starts to translate the image is displaced in y axis. Here is a picture of what happpens.
But when i use an xml to translate everything works fine. What is the problem with my code ?
Xml:
<translate
android:fromXDelta="0%p"
android:toXDelta="80%p"
android:duration="200"
android:fillAfter="true"
/>
I can't understand why, but
circleImage.animate().
translationXBy(width).
setDuration(200).
start();
solved my problem. I think maybe its a problem with final Animation animTrans = new TranslateAnimation(0f, 1f, 0f, 0f);. Those xdelta, ydelta values may be the reason.
I am writing a launcher.
How do I start an activity to show the Marshmallow animation?
I have looked at the AOSP Launcher3 source and only found it to use this:
if (useLaunchAnimation) {
ActivityOptions opts = Utilities.isLmpOrAbove() ?
ActivityOptions.makeCustomAnimation(this, R.anim.task_open_enter, R.anim.no_anim) :
ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
optsBundle = opts.toBundle();
}
Which then get fed into
startActivity(context, optsBundle);
Where the task_open_enter animation looks like this:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#ff000000"
android:shareInterpolator="false"
android:zAdjustment="top">
<alpha
android:duration="167"
android:fillAfter="true"
android:fillBefore="true"
android:fillEnabled="true"
android:fromAlpha="0"
android:interpolator="#interpolator/decelerate_quart"
android:startOffset="0"
android:toAlpha="1.0" />
<translate
android:duration="417"
android:fillAfter="true"
android:fillBefore="true"
android:fillEnabled="true"
android:fromYDelta="110%"
android:interpolator="#interpolator/decelerate_quint"
android:startOffset="0"
android:toYDelta="0" />
</set>
Unfortunately these are not the same as the Marshmallow animation I am looking for, as shown below:
(gif is slowed down 3 times)
I found the answer in the launcher source code here:
Bundle optsBundle = null;
ActivityOptions opts = null;
if (Utilities.ATLEAST_MARSHMALLOW) {
int left = 0, top = 0;
int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
// if (v instanceof TextView) {
// // Launch from center of icon, not entire view
// Drawable icon = Workspace.getTextViewIcon((TextView) v);
// if (icon != null) {
// Rect bounds = icon.getBounds();
// left = (width - bounds.width()) / 2;
// top = v.getPaddingTop();
// width = bounds.width();
// height = bounds.height();
// }
// }
opts = ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
} else if (!Utilities.ATLEAST_LOLLIPOP) {
// Below L, we use a scale up animation
opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
} else if (Utilities.ATLEAST_LOLLIPOP_MR1) {
// On L devices, we use the device default slide-up transition.
// On L MR1 devices, we use a custom version of the slide-up transition which
// doesn't have the delay present in the device default.
opts = ActivityOptions.makeCustomAnimation(context, R.anim.task_open_enter, R.anim.no_anim);
}
optsBundle = opts != null ? opts.toBundle() : null;
context.startActivity(intent, optsBundle);
I have a RelativeLayout with an ImageView inside it. ImageView is positioned randomly inside a layout. I'm trying to apply translate animation, which will translate the ImageView from it's current position (x,y) to the center of screen (x,y).
I have tried something like code below, but it doesn't do the trick.
<translate
android:fromXDelta="0%"
android:toXDelta="50%"
android:fromYDelta="0%"
android:toYDelta="50%"
android:duration="500"/>
Help appreciated ;)
MY Code:
Understand...
Point windowSize = new Point();
int totalWidth;
//obtem o tamanho da tela que estamos trabalhando no momento
if(Build.VERSION.SDK_INT > 12) {
windowManager.getDefaultDisplay().getSize(windowSize);
totalWidth = windowSize.x;
}
else
totalWidth = windowManager.getDefaultDisplay().getWidth();
//vamos animar ao centro
final int totalWidthFinal = ((totalWidth / 2) - (int)getDimension(R.dimen.fab_actions_spacing)) * -1;
mFloatingActionButton.post(new Runnable() {
#Override
public void run() {
int translationX = totalWidthFinal;
ViewPropertyAnimator.animate(mFloatingActionButton).setDuration(300).translationX(translationX);
}
});
I'm trying to create an AndEngine HUD that will sit on top of a TMXTiledMap (bear with me, I'm very new to AndEngine). To keep things simple at first, I have a simple rectangle created via Android drawables. The idea is that this will sit at the bottom center of the screen and never move, even as the map underneath it is moved in various directions. For now, all I want to do is get that rectangle to show up. Later on I'll add other functionality to the rectangle.
My drawable is created like this:
?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners
android:radius="7dp" />
<gradient
android:startColor="#343434"
android:endColor="#17171717"
android:angle="270"
android:useLevel="false"
android:type="linear" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
</shape>
And I have it pulled into a layout like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="300dip"
android:layout_height="100dip"
android:orientation="horizontal"
android:layout_marginLeft="20dp"
android:background="#drawable/menu_bkgrnd" >
</LinearLayout>
And then finally, here is where I try to pull it in as a HUD:
rect = new HUD();
ITouchArea container = (ITouchArea) findViewById(R.id.container);
this.rect.registerTouchArea(container);
rect.attachChild((IEntity) container);
As you can see, I'm doing a lot of casting to satisfy AndEngine, but when I run this, the map is totally screwed up. Am I going about this correctly? Is my casting incorrect? (or maybe both!).
Thanks for any help.
EDIT:
Based on the code that Jong and 正宗白布鞋 suggested below, I've adjusted my Java code as follows:
this.atlas = new BitmapTextureAtlas(null, 256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.atlas.load();
ITextureRegion drawable = BitmapTextureAtlasTextureRegionFactory.createFromResource(atlas, getApplicationContext(), R.drawable.myDrawable, 0, 0);
rect.attachChild(new Sprite(0, 0, drawable, this.getVertexBufferObjectManager()));
At this point, I'm still just trying to get this to appear on the screen. I'll adjust size and location later.
Everything compiles and runs without error, however my screen is just a total mess.
As you can see, I had to make a couple of small adjustments to the constructor arguments to get AndEngine to accept my instantiations. Not sure if I'm doing this correctly.
The other issue that I see in this code is that it appears to me that this code is just going to place an inactive shape on my screen. I know that in my original post, I said that my immediate goal is to make this rectangle show up, but I think that it has to show up as a registered touch area since it will ultimately be something with controls on it that need to respond to user commands. Sorry if I overly minimized what I am trying to do.
I'm still not getting this. Anybody have any suggestions? Thanks again!
You can't cast LinearLayout to ITouchArea, ITouchArea is an interface implemented by AndEngine classes only.
Like 正宗白布鞋 suggested, you should use the createFromResource method of BitmapTextureAtlasTextureRegionFactory.
You can use this code:
BitmapTextureAtlas atlas = new BitmapTextureAtlas(sizeX, sizeY, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
TextureRegion drawable = BitmapTextureAtlasTextureRegionFactory.createFromResource(atlas, getApplicationContext(), R.drawable.drawableId, 0, 0);
rect.attachChild(new Sprite(x, y, drawable));
EDIT:
If you want your sprite to respond to touch events, you can register it as a touch area in your rect HUD.
Sprite sprite = new Sprite(x, y, drawable, getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pTouchEvent, final float pX, final float pY) {
//Do what you want here
}
}
rect.registerTouchArea(sprite);
rect.attachChild(sprite);
I had the same problem several days ago, and I couldn't find a proper answer. So now that I've gathered information from different sources, here is how I dealt with this.
AFAIK, it appears that the method createFromResource(atlas, getApplicationContext(), R.drawable.drawableId, 0, 0) from BitmapTextureAtlasTextureRegionFactory cannot deal with XML drawable (such as <shape>...</shape>).
Indeed, when I was only displaying a colored rectangle, everything was fine - and I think with a PNG file too -, but when I tried to create a Sprite from my XML drawable, I always got a NullBitmapException when the drawing happened.
Steps I took:
Convert drawable resource to Drawable
Convert Drawable to Bitmap (Source here)
Convert Bitmap to TextureRegion (This is where I used this)
Create a Sprite from the TextureRegion (or two for selected/unselected, like here)
Attach the Sprite to the game's HUD
So, with code:
Convert drawable resource TextureRegion
/**
* Takes a drawable, and converts it to a TextureRegion.
* #param context
* #param resId the drawable ID
* #param textureSizeX width for our TextureRegion
* #param textureSizeY height for our TextureRegion
* #return a TextureRegion from the drawable
*/
public static TextureRegion textureRegionFromDrawable(BaseGameActivity context, int resId, int textureSizeX, int textureSizeY) {
Drawable drawable = context.getResources().getDrawable(resId);
Bitmap bitmap = drawableToBitmap(drawable);
BitmapTextureAtlasTextureSource source = new BitmapTextureAtlasTextureSource(bitmap);
BitmapTextureAtlas textureAtlas = new BitmapTextureAtlas(context.getTextureManager(), textureSizeX, textureSizeY);
textureAtlas.addTextureAtlasSource(source, 0, 0);
textureAtlas.load();
TextureRegion textureRegion = (TextureRegion) TextureRegionFactory.createFromSource(textureAtlas, source, 0, 0);
return textureRegion;
}
// Drawable to Bitmap
public static Bitmap drawableToBitmap(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
The utility intermediary class
public class BitmapTextureAtlasTextureSource extends BaseTextureAtlasSource implements IBitmapTextureAtlasSource {
private final int[] mColors;
public BitmapTextureAtlasTextureSource(Bitmap pBitmap) {
super(0, 0, pBitmap.getWidth(), pBitmap.getHeight());
mColors = new int[mTextureWidth * mTextureHeight];
for (int y = 0; y < mTextureHeight; ++y) {
for (int x = 0; x < mTextureWidth; ++x) {
mColors[x + y * mTextureWidth] = pBitmap.getPixel(x, y);
}
}
}
#Override
public Bitmap onLoadBitmap(Config pBitmapConfig) {
return Bitmap.createBitmap(mColors, mTextureWidth, mTextureHeight, Bitmap.Config.ARGB_8888);
}
#Override
public IBitmapTextureAtlasSource deepCopy() {
return new BitmapTextureAtlasTextureSource(Bitmap.createBitmap(mColors, mTextureWidth, mTextureHeight, Bitmap.Config.ARGB_8888));
}
#Override
public Bitmap onLoadBitmap(Config pBitmapConfig, boolean pMutable) {
// TODO Auto-generated method stub
return null;
}
}
Create two Sprite from the TextureRegions (I wanted 2 states for my button: selected/unselected), and attach them to the HUD
int textureSizeX = 512, textureSizeY = 512;
TextureRegion textureDefault = AndEngineUtils.textureRegionFromDrawable(activity, R.drawable.custom_menu_button, textureSizeX, textureSizeY);
TextureRegion textureSelected = AndEngineUtils.textureRegionFromDrawable(activity, R.drawable.custom_menu_button_selected, textureSizeX, textureSizeY);
mGameHUD = new HUD();
// 2 sprites for selected and unselected
final Sprite buttonUnselected, buttonSelected ;
buttonSelected = new Sprite(0, 0, textureSelected, activity.getVertexBufferObjectManager());
buttonSelected.setVisible(false);
buttonUnselected = new Sprite(0, 0, textureDefault, activity.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {
switch (pSceneTouchEvent.getAction()) {
case TouchEvent.ACTION_DOWN:
// Change button
buttonSelected.setVisible(true);
this.setVisible(false);
break;
case TouchEvent.ACTION_UP:
// reset button
this.setVisible(true);
buttonSelected.setVisible(false);
break;
default:
break;
}
return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);
}
};
mGameHUD.attachChild(buttonSelected);
mGameHUD.attachChild(buttonUnselected);
mGameHUD.registerTouchArea(buttonUnselected);
camera.setHUD(mGameHUD);
We can also make use of scene.setOnAreaTouchListener(touchListener) in order for an "unwanted" sliding gesture - until outside of the button - to take effet to reset the button color (see this thread).
I have just begun using AndEngine and I am not yet familiar with best practices, so feel free to correct me.
I have a xml file :
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/header"
android:tileMode="repeat" />
I have a header and I would like to repeat my drawable only in X and stretch it in Y. How could I do that in xml.
first try :
I remove my xml and I've done that at the beginning of my activity:
BitmapDrawable bp =(BitmapDrawable)getResources().getDrawable(R.drawable.header);
bp.setTileModeX(TileMode.REPEAT);
LinearLayout layout = (LinearLayout)findViewById(R.id.headerRedLayout);
layout.setBackgroundDrawable(bp);
It works great but I would like that the repeat starts at the bottom of the layout
In the onDraw() method do this
keep in mind R.drawable.bg_tile is your image
protected void onDraw (Canvas canvas) {
bgTile = BitmapFactory.decodeResource(context.getResources(), R.drawable.bg_tile);
float left = 0;
float top = 0;
float bgTileWidth = bgTile.getWidth();
int screenWidth = canvas.getWidth(); //Not sure of this
int screenHeight = canvas.getHeight(); //Not sure of this too
while (left < screenWidth) {
canvas.drawBitmap(
bgTile,
null,
new Rect(left,top,left+bgTileWidth,screenHeight),
null
);
left += bgTileWidth;
}
}