Zoom multiple sprites, individually on touch-Andengine - sprite

I am very new to andEngine, I want to add sprites on screen and let them move and zoom on finger touch.
Right now i am able to add multiple sprites on scene , and they can be dragged on touch.
Here is my code:
public class Main extends SimpleBaseGameActivity {
#Override
private Camera camera;
private BitmapTextureAtlas mBitmapTextureAtlas;
private ITextureRegion mFaceTextureRegion;
private ITextureRegion mFaceTextureRegion2;
private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;
#Override
public EngineOptions onCreateEngineOptions() {
camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions engineOptions = new EngineOptions(true,
ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(
CAMERA_WIDTH, CAMERA_HEIGHT), camera);
return engineOptions;
}
#Override
protected void onCreateResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.mBitmapTextureAtlas = new BitmapTextureAtlas(
this.getTextureManager(), 1024, 1600, TextureOptions.NEAREST);
// background
// this.background = new Sprite(0, 0,
// BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas,
// this, "ui_ball_1.png", 0, 0, 1, 1),
// this.getVertexBufferObjectManager());
this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(this.mBitmapTextureAtlas, this,
"ui_ball_1.png", 0, 0);
this.mFaceTextureRegion2 = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(this.mBitmapTextureAtlas, this,
"ui_ball_1.png", 0, 0);
this.mBitmapTextureAtlas.load();
// this.mEngine.getTextureManager().loadTexture(this.mBitmapTextureAtlas);
/*
* this.mBitmapTextureAtlas = new
* BitmapTextureAtlas(this.getTextureManager(), 32, 32,
* TextureOptions.BILINEAR); this.mFaceTextureRegion =
* BitmapTextureAtlasTextureRegionFactory
* .createFromAsset(this.mBitmapTextureAtlas, this, "ui_ball_1.png", 0,
* 0); this.mBitmapTextureAtlas.load();
*/
}
#Override
protected Scene onCreateScene() {
/*
* this.scene = new Scene(); this.scene.attachChild(this.background);
* this.scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
* return this.scene;
*/
this.mEngine.registerUpdateHandler(new FPSLogger());
final Scene scene = new Scene();
scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion
.getWidth()) / 2;
final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion
.getHeight()) / 2;
final Sprite face = new Sprite(centerX, centerY,
this.mFaceTextureRegion, this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
face.setScale(2);
scene.attachChild(face);
scene.registerTouchArea(face);
final Sprite face2 = new Sprite(0, 0, this.mFaceTextureRegion2,
this.getVertexBufferObjectManager()) {
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
return true;
}
};
face2.setScale(2);
scene.attachChild(face2);
scene.registerTouchArea(face2);
scene.setTouchAreaBindingOnActionDownEnabled(true);
return scene;
}
}
Now i want to zoom each sprite on touch, but unable to find such method like setPosition available to move sprite to a specific position. Can anyone help me in achieving this without affecting the current functionality. Any help would be appreciated, may be in form of code or some direction/method to do this.
Thanks in advance :)

you can use a EntityModifier to make your effect:
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent,
final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
this.clearEntityModifiers();
this.RegisterEntityModifier(new ScaleModifier(1f,2f,4f));
//1f = time to convert the scale of sprite of 2f to 4f
//2f = initial scale
//4f = finish scale
//when you dont touch the sprite back to normal scale
if(event.getAction()== MotionEvent.ACTION_UP) {
this.clearEntityModifiers();
this.RegisterEntityModifier(new ScaleModifier(1f,4f,2f));
}
//you also can work with "MotionEvent.ACTION_DOWN" and
//MotionEvent.ACTION_MOVE
return true;
}

Related

Android Studio Opengl ES get problem with weird color mixturing

Basically I've created a plane and rotate it 5 times to be a cube. I made cube with different colors of each side. And did some rotation with touch event.
Everthing was good so far, but the cube turned out to be like this.
Please help it's been driving me crazy!
My cube code:
public class PhotoCube{
public ArrayList<FloatBuffer> vertexBufferList = new ArrayList<>();
public int[][] lists = {
{0,1,0,0}, //front
{1,0,0,-90}, //top
{0,1,0,-90}, //left
{0,1,0,90}, //
{1,0,0,90}, //bottom
{0,1,0,180} //right
};
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static final float[] coords = { // in counterclockwise order:
0.5f, 0.5f, 0.5f, // top right
-0.5f, 0.5f, 0.5f, // top left
-0.5f, -0.5f, 0.5f, // bottom left
0.5f, -0.5f, 0.5f // bottom right
};
static final float[][] colorList = {
{1f,0f,0f,1f},
{0f,1f,0f,1f},
{1f,1f,1f,1f},
{1f,1f,0f,1f},
{1f,0f,1f,1f},
{0f,1f,1f,1f}
};
public PhotoCube() {
final int maxVertices = 6;
for(int[] list:lists){
float[] currentCoords = coords.clone();
for(int i=0;i<12;i+=3){
float x = coords[i];
float y = coords[i+1];
float z = coords[i+2];
double angle = Math.toRadians(list[3]);
currentCoords[i]=(float) ((list[0]==1)?x:(list[1]==1)?x*Math.cos(angle)+z*Math.sin(angle):x*Math.cos(angle)-y*Math.sin(angle));
currentCoords[i+1]=(float) ((list[0]==1)?y*Math.cos(angle)-z*Math.sin(angle):(list[1]==1)?y:x*Math.sin(angle)+y*Math.cos(angle));
currentCoords[i+2]=(float) ((list[0]==1)?z*Math.cos(angle)+y*Math.sin(angle):(list[1]==1)?z*Math.cos(angle)-x*Math.sin(angle):z);
}
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
currentCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
FloatBuffer vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(currentCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
if(vertexBufferList.size()==maxVertices){
vertexBufferList.remove(0);
}
vertexBufferList.add(vertexBuffer);
ByteBuffer dlb = ByteBuffer.allocateDirect(
// (# of coordinate values * 2 bytes per short)
drawOrder.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
createProgram();
GLES20.glLinkProgram(mProgram);
// creates OpenGL ES program executables
}
}
public void createProgram(){
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
}
public void draw(int order) {
final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(positionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, true,
vertexStride, vertexBufferList.get(order));
// get handle to fragment shader's vColor member
int colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(colorHandle, 1, colorList[order], 0);
GLES20.glDrawElements(
GLES20.GL_TRIANGLES,
drawOrder.length,
GL_UNSIGNED_SHORT,
drawListBuffer);
// Disable vertex array
//GLES20.glDisableVertexAttribArray(positionHandle);
}
}
My Renderer code:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private PhotoCube mPhotoCube;
public final float[] vPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = new float[16];
private int vPMatrixHandle = -1;
private volatile float mAngleX = 0;
private volatile float mAngleY = 0;
private float[] rotationMX = new float[16];
private float[] rotationMY = new float[16];
private float[] scratch = new float[16];
public MyGLRenderer(Context context){
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
mPhotoCube = new PhotoCube();
vPMatrixHandle = GLES20.glGetUniformLocation(mPhotoCube.mProgram, "uVPMatrix");
onDrawFrame(unused);
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFuncSeparate(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA, GLES20.GL_ZERO, GLES20.GL_ONE);
Matrix.setRotateM(rotationMX, 0, -mAngleX, 0, 1, 0);
Matrix.setLookAtM(viewMatrix, 0, 0, 0, 5, 0f, 0f, -5f, 0f, 1.0f, 0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(scratch, 0, vPMatrix, 0, rotationMX, 0);
Matrix.setRotateM(rotationMY, 0, -mAngleY, scratch[0], scratch[4], scratch[8]);
Matrix.multiplyMM(scratch, 0, scratch, 0, rotationMY, 0);
vPMatrixHandle = GLES20.glGetUniformLocation(mPhotoCube.mProgram, "uMVPMatrix");
GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, scratch, 0);
for(int i=0;i<mPhotoCube.lists.length;i++){
mPhotoCube.draw(i);
}
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
}
Here's my shader code
final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
Thank you in advance.
You have to enable the Depth Test Depth test ensures that fragments that lie behind other fragments are discarded:
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
When you enable the depth test you must also clear the depth buffer:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
However, if you have transparent objects and want to use Blending, the depth test must be disabled and you must draw the triangles of the meshes in sorted order from back to front. Also see OpenGL depth sorting

LibGDX draws dots instead of lines

I would like to implement some kind of eraser,so in my render method I make the upper layer transparent.
#Override
public void render () {
cam.update();
Gdx.gl.glClearColor(1, 1, 1,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (Gdx.input.isTouched()) {
pos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
pixmap.setColor(new Color(1, 1, 1, 0.5f)); //transparency
pixmap.fillCircle((int)pos.x, (int)pos.y, 10);
}
texture3.draw(pixmap, 0, 0);
batch.begin();
batch.draw(texture, 0, 0);
batch.draw(texture3, 0, 0);
batch.end();
}
But I got points when make swipes. It requires to do very slow speed to make lines instead of dots.
So I expect continuous line instead of dots.
Can you advice something please?
Dots instead of line
This is caused because of the frequency at which the input state is updated, the solution here would be to manually calculate the missing points needed to make a line, you could do this with a linear interpolation between each pair of dots, additionally you could calculate how many extra dots are necessary depending on how far is the newest dot from the previous one, in my example I use an arbitrary number of extra dots (20) like so:
public class TestDraw extends Game {
private Pixmap pixmap;
private Texture texture;
private SpriteBatch batch;
private Vector2 lastPos;
#Override
public void create() {
pixmap = new Pixmap(1000, 1000, Pixmap.Format.RGBA8888);
texture = new Texture(pixmap);
batch = new SpriteBatch();
lastPos = new Vector2();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (Gdx.input.isTouched()) {
pixmap.setColor(new Color(1, 1, 1, 0.5f)); //transparency
int newX = Gdx.input.getX();
int newY = Gdx.input.getY();
pixmap.setColor(Color.RED);
pixmap.fillCircle(newX, newY, 10);
// If the distance is too far, fill with extra dots
if (lastPos.dst(newX, newY) > 10) { // Here far is 10, you can adjust as needed
int extraDots = 20; // How many extra dots to draw a line, I use 20, adjust as needed or calculate according to distance (for example lastPos.dst(newX,newY) * 5)
for (int i = 0; i < extraDots; i++) {
float progress = (1f / extraDots) * i;
int dotX = (int) MathUtils.lerp(lastPos.x, newX, progress);
int dotY = (int) MathUtils.lerp(lastPos.y, newY, progress);
pixmap.setColor(Color.BLUE);
pixmap.fillCircle(dotX, dotY, 10);
}
}
// Store last position for next render() call
lastPos.set(newX, newY);
}
texture.draw(pixmap, 0, 0);
batch.begin();
batch.draw(texture, 0, 0);
batch.end();
}
}
Adecuate to your code as needed, I didn't know what was texture3 so I didn't include in my example
Also another option which I don't like too much because of rendering and storage cost is using a Polygon to draw the lines.

GLSL shader circle is wobbling as it changes size in LibGDX

In LibGDX, I created a shader to do a transition effect where a circle forms over top of the image, where everything outside the circle is black, and everything inside the circle shows up as normal. This circle starts out big and shrinks to nothing. But I have a problem, as the circle is shrinking, it wobbles around. I also found I had this problem when using a ShadeRenderer to create a circle that also shrank over time, before using a shader. I think the problem as something to do with floating point numbers, or the way that circles are rendered. Anyway, I need to know, how do I fix it, so that I can get the circle to shrink smoothly?
Here is a gif demonstrating my problem of the wobbling circle (which I need to be smooth): my wobbling circle
Here is my Fragment Shader Code:
varying vec4 v_color;
varying vec3 v_position;
varying vec2 v_texCoord0;
uniform vec2 u_resolution;
uniform sampler2D u_sampler2D;
uniform float u_radius;
uniform int u_hasCircle;
void main() {
vec4 color = texture2D(u_sampler2D, v_texCoord0) * v_color;
vec2 relativePosition = gl_FragCoord.xy / u_resolution - .5;
relativePosition.x *= u_resolution.x / u_resolution.y;
float len = length(relativePosition);
if (u_hasCircle == 1 && len > u_radius) {
color = vec4(0, 0, 0, 1);
}
gl_FragColor = color;
}
And here is my vertex shader code that runs before that:
attribute vec4 a_color;
attribute vec3 a_position;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
uniform vec3 u_distort;
varying vec4 v_color;
varying vec3 v_position;
varying vec2 v_texCoord0;
void main() {
v_color = a_color;
v_position = a_position;
v_texCoord0 = a_texCoord0;
gl_Position = u_projTrans * vec4(a_position, 1.0);
}
When I want to transition to run, u_hasCircle is passed 1, otherwise it is passed 0. When the transition is running, I start with passing u_radius 1, and then I gradually decrease the value to 0, using a FloatAction in LibGDX.
I send these values to the shader once per frame.
Here is the relevant Libgdx Java code that interacts with the shader:
public class PlayWorld extends Group implements InputProcessor, Disposable
{
//various members
private PlayScreen screen;
private OrthographicCamera camera;
private FloatAction transitionToBattleAction;
private final float TRANS_TO_BATTLE_DURATION = 10f;
private float circleSize;
private boolean hasCircle = false;
public PlayWorld(PlayWorld playWorld) {
this.playWorld = playWorld;
camera = new OrthographicCamera();
tiledMap = new TiledMapActor(camera);
addActor(tiledMap);
transitionToBattleAction = new FloatAction();
}
//function that triggers transition
public void enterBattle() {
transitionToBattleAction.reset();
transitionToBattleAction.setStart(0);
transitionToBattleAction.setEnd(1);
transitionToBattleAction.setDuration(TRANS_TO_BATTLE_DURATION);
addAction();
}
// this function gets called every frame
#Override
public void act(float delta) {
super.act(delta);
if (transitionToBattleAction.getValue() == 0) {
//this function is defined in code shown below
tiledMap.unsetCircleSize();
} else if (transitionToBattleAction.getValue() < 1) {
//this function is defined in code shown below
tiledMap.setCircleSize(
1 - transitionToBattleAction.getValue());
} else if (transitionToBattleAction.getValue() == 1) {
//this function is defined in code shown below
tiledMap.setCircleSize(
1 - transitionToBattleAction.getValue());
transitionToBattleAction.restart();
screen.getGame().setScreen("battle");
} else if (transitionToBattleAction.getValue() > 1) {
//this function is defined in code shown below
tiledMap.unsetCircleSize();
transitionToBattleAction.restart();
}
}
//this gets called whenever the window resizes
public void resize(int width, int height) {
// this function is defined in code shown below
tiledMap.resize(width, height);
}
//various other methods
}
public class TiledMapActor extends Actor implements InputProcessor, Disposable
{
//various variables
private ShaderProgram shader;
private OrthographicCamera camera;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private float UNIT_SCALE = 1 / 16f;
public TiledMapActor(OrthographicCamera camera) {
super();
this.camera = camera;
map = new TmxMapLoader().load("myMap.tmx");
renderer = new OrthogonalTiledMapRenderer(map, UNIT_SCALE);
shader = new ShaderProgram(
Gdx.files.internal("shaders/myshader.vsh"),
Gdx.files.internal("shaders/myshader.fsh");
System.out.println(
shader.isCompiled() ?
"shader compiled" : shader.getLog());
renderer.getBatch().setShader(shader);
shader.begin();
shader.setUniformi("u_hasCircle", 0);
shader.end();
}
// this is called every time the window changes size
// from the PlayScreen class, see code above
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();
shader.begin();
shader.setUniformf("u_resolution", (float)width, (float)height);
shader.end();
}
//this method is called from code above, seen PlayScreen class code
//
public void setCircleSize(float circleSize) {
this.circleSize = circleSize;
hasCircle = true;
shader.begin();
shader.setUniformf("u_radius", circleSize);
shader.setUniformi("u_hasCircle", 1);
shader.end();
}
//this method is called from code above, seen PlayScreen class code
//
public void unsetCircleSize() {
hasCircle = false;
shader.begin();
shader.setUniformi("u_hasCircle", 0);
shader.end();
}
// Various other methods
}
So I found the problem, and stupid me! I was re-entering the transition scene every frame, once it started. I fixed it by using a boolean flag to tell me if the transition had started, and only starting the transition if that boolean flag wasn't set yet. Then later, at a point, after the transition had completed, I set that boolean flag back to false, so the transition could occur again!

TextureRegion cuts texture in a wrong way

I want to have a background texture with 3 rectangles and i want to create animation with them, - texture
But first rectangle cuts in a proper way and two others are cut in a dumb way
Proper way,
Dumb way #1,
Dumb way #2
Here is my code.
public class MainMenu implements Screen{
Texture background_main;
TextureRegion[] background_textures;
Animation background_animation;
SpriteBatch batch;
TextureRegion current_frame;
float stateTime;
BobDestroyer game;
OrthographicCamera camera;
public MainMenu(BobDestroyer game){
this.game = game;
}
#Override
public void show() {
camera = new OrthographicCamera();
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch = new SpriteBatch();
background_main = new Texture(Gdx.files.internal("main_menu_screen/Background.png"));
background_textures = new TextureRegion[3];
for(int i = 0; i<3; i++){
background_textures[i] = new TextureRegion(background_main,0, 0+72*i, 128, 72+72*i);
}
background_animation = new Animation(2f,background_textures);
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
current_frame = background_animation.getKeyFrame(stateTime, true);
batch.begin();
batch.draw(current_frame,0, 0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
batch.end();
}
}
If I understand you correctly, are you trying to create 3 TextureRegions of the same width/height? If yes, your issue may be with:
new TextureRegion(background_main,0, 0+72*i, 128, 72+72*i)
I think you'd want:
new TextureRegion(background_main,0, 0+72*i, 128, 72)
As the 128x72 is the width/height (not x/y positions) of your next TextureRegions, and do you not want them all the same height (72) as opposed to varying heights (72+72*i)?

How do I create an Android material design UI widget?

I did read new android material design guide but i am not able to find anything about how to create this UI widget(element). Apps like Gmail, S converter etc has updated their apps to support new material design.
I have added screenshot of it. Here is the link to it. because of low points i can't put the picture. sorry about it
Any suggestions on how shall i make it??
You are talking about the Floating Action Button. Bottom line is: there is no native "FAB" widget (at least for now), it is a custom layout that must be implemented.
If you really want to fully implement a Material Design app, I recommend you take a look at Google's 2014 I/O app. They have an example of a FAB layout here.
Here's also the code to create one. It is from this gist.
public class FloatingActionButton extends View {
Context context;
Paint mButtonPaint;
Paint mDrawablePaint;
Bitmap mBitmap;
boolean mHidden = false;
public FloatingActionButton(Context context) {
super(context);
this.context = context;
init(Color.WHITE);
}
public void init(int color) {
setWillNotDraw(false);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mButtonPaint.setColor(color);
mButtonPaint.setStyle(Paint.Style.FILL);
mButtonPaint.setShadowLayer(10.0f, 0.0f, 3.5f, Color.argb(100, 0, 0, 0));
mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
setClickable(true);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);
canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,
(getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
setAlpha(1.0f);
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
setAlpha(0.6f);
}
return super.onTouchEvent(event);
}
public void setColor(int color) {
init(color);
}
public void setDrawable(Drawable drawable) {
mBitmap = ((BitmapDrawable) drawable).getBitmap();
invalidate();
}
public void hide() {
if (!mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1, 0);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1, 0);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(new AccelerateInterpolator());
animSetXY.setDuration(100);
animSetXY.start();
mHidden = true;
}
}
public void show() {
if (mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0, 1);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(new OvershootInterpolator());
animSetXY.setDuration(200);
animSetXY.start();
mHidden = false;
}
}
public boolean isHidden() {
return mHidden;
}
public static class Builder {
private FrameLayout.LayoutParams params;
private final Activity activity;
int gravity = Gravity.BOTTOM | Gravity.RIGHT; // default bottom right
Drawable drawable;
int color = Color.WHITE;
int size = 0;
float scale = 0;
/**
* Constructor using a context for this builder and the
* {#link FloatingActionButton} it creates
* #param context
*/
public Builder(Activity context) {
scale = context.getResources().getDisplayMetrics().density;
// The calculation (value * scale + 0.5f) is a widely used to convert to dps to pixel
// units based on density scale
// see <a href="http://developer.android.com/guide/practices/screens_support.html">
// developer.android.com (Supporting Multiple Screen Sizes)</a>
size = (int) (72 * scale + 0.5f); // default size is 72dp by 72dp
params = new FrameLayout.LayoutParams(size, size);
params.gravity = gravity;
this.activity = context;
}
/**
* Sets the FAB gravity.
*/
public Builder withGravity(int gravity) {
this.gravity = gravity;
return this;
}
/**
* Sets the FAB margins in dp.
*/
public Builder withMargins(int left, int top, int right, int bottom) {
params.setMargins((int) (left * scale + 0.5f), (int) (top * scale + 0.5f),
(int) (right * scale + 0.5f), (int) (bottom * scale + 0.5f));
return this;
}
/**
* Sets the FAB drawable.
*
* #param drawable
*/
public Builder withDrawable(final Drawable drawable) {
this.drawable = drawable;
return this;
}
/**
* Sets the FAB color.
*
* #param color
*/
public Builder withColor(final int color) {
this.color = color;
return this;
}
/**
* Sets the FAB size.
*
* #param size
* #return
*/
public Builder withSize(int size) {
size = (int) (size * scale + 0.5f);
params = new FrameLayout.LayoutParams(size, size);
return this;
}
/**
* Creates a {#link FloatingActionButton} with the
* arguments supplied to this builder.
*/
public FloatingActionButton create() {
final FloatingActionButton button = new FloatingActionButton(activity);
button.setColor(this.color);
button.setDrawable(this.drawable);
params.gravity = this.gravity;
ViewGroup root = (ViewGroup) activity.findViewById(android.R.id.content);
root.addView(button, params);
return button;
}
}
}
Then you would add like this:
FloatingActionButton mFab = new FloatingActionButton.Builder(this)
.withColor(getResources().getColor(R.color.accent_color))
.withDrawable(getResources().getDrawable(R.drawable.fab_icon))
.withSize(72)
.withMargins(0, 0, 16, 16)
.create();

Resources