When writing in the Textfield, I need my textfield to move upwards in order to let the textfield be visible when the keyboard pops up.
Does libgdx have some kind of method which returns true if the keyboard is visible and false when it is down?
The following code will detect when you press a textfield, prevent it from showing the keyboard and then open a native dialog that moves up and down with the keyboard. It will take the input from the native dialog and finally put it back in your textField:
textField.setOnscreenKeyboard(new TextField.OnscreenKeyboard() {
#Override
public void show(boolean visible) {
//Gdx.input.setOnscreenKeyboardVisible(true);
Gdx.input.getTextInput(new Input.TextInputListener() {
#Override
public void input(String text) {
textField.setText(text);
}
#Override
public void canceled() {
System.out.println("Cancelled.");
}
}, "Title", "Default text...");
}
});
Good Luck!
I know I'm answering to an old thread, but I was googling to find an answer to this question but couldn't find it anywhere. Now I have created a solution myself. Here is how to do it on Android in an elegant way :)
I'm creating an ApplicationBundle to bundle interfaces to add platform specific things. You can do this on iOS too if you want to make use of RoboVM.
My solution:
create a SizeChangeListener interface in the core project:
public interface SizeChangeListener {
public void onSizeChange(float width, float height);
}
create a View interface in the core project:
public interface View {
public void onSizeChange(float width, float height);
public void addListener(SizeChangeListener sizeChangeListener);
public float getWidth();
public float getHeight();
}
create an AndroidView implementing the View interface:
public class AndroidView implements View {
private ArrayList<SizeChangeListener> listeners = new ArrayList<SizeChangeListener>();
private float width, height;
public AndroidView(int width, int height) {
this.width = width;
this.height = height;
}
public void addListener(SizeChangeListener listener) {
listeners.add(listener);
}
public void onSizeChange(float width, float height) {
this.width = width;
this.height = height;
for(SizeChangeListener listener : listeners)
listener.onSizeChange(width, height);
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
}
create an ApplicationBundle in the core project
public class ApplicationBundle {
private final View view;
public ApplicationBundle(View view) {
this.view = view;
}
public View getView() {
return view;
}
}
Make the necessary imports from the core project. In the AndroidLauncher in the Android project add the following:
public class AndroidLauncher extends AndroidApplication {
private View rootView;
private AndroidView androidView;
private int width, height;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
rootView = this.getWindow().getDecorView().getRootView();
Rect rect = new Rect();
rootView.getWindowVisibleDisplayFrame(rect);
width = rect.width();
height = rect.height();
androidView = new AndroidView(width, height);
rootView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
Rect rect = new Rect();
rootView.getWindowVisibleDisplayFrame(rect);
if(!(width == rect.width() && height == rect.height())) {
width = rect.width();
height = rect.height();
androidView.onSizeChange(width, height);
}
}
});
initialize(new DigMeApp(new ApplicationBundle(androidView)), config);
}
}
In your main MyApp in the core project in the create() method add a SizeChangeListener implementation to the view you've got from the constructor.
public class MyApp extends Game { // or ApplicationAdapter
private View view;
private Stage stage;
// your own variables
public MyApp(ApplicationBundle applicationBundle) {
view = applicationBundle.getView();
}
#Override
public void create () {
stage = new Stage();
// add some textfields
final TextField tf1 = new TextField("", skin);
final TextField tf2 = new TextField("", skin);
tf1.setWidth((float)view.getWidth() * 0.6f);
tf2.setWidth((float)view.getWidth() * 0.6f);
tf1.setHeight((float)view.getHeight() * 0.05f);
tf2.setHeight((float)view.getHeight() * 0.05f);
view.addListener(new SizeChangeListener() {
#Override
public void onSizeChange(float width, float height) {
Gdx.app.log("INFO", "Visible area: " + width + " " + height);
Gdx.app.log("INFO", "Stage area: " + stage.getWidth() + " " + stage.getHeight());
float keyboardHeight = getKeyboardHeight();
// MOVE THEM OUT OF THE WAY :)
tf1.addAction(Actions.moveTo(width / 2 - tf1.getWidth() / 2.0f, keyboardHeight + (6 * (height / 8)), 1, Interpolation.sineOut));
tf2.addAction(Actions.moveTo(width / 2 - tf2.getWidth() / 2.0f, keyboardHeight + (7 * (height / 8)), 1, Interpolation.sineOut));
// Gdx.gl20.
// tf.setPosition(width / 2 - (tf.getWidth() / 2.0f), 0);
}
});
}
Perhaps create a little keyboard heigt method like I did:
private float getKeyboardHeight() {
return stage.getHeight() - view.getHeight();
}
Try
Gdx.input.isPeripheralAvailable(Input.Peripheral.OnscreenKeyboard);
I just looked this up in the docs, don't know if it actually does the trick. But the
Gdx.input.setOnscreenKeyboardVisible(boolean visible);
method could be used as well (like this YOU define when the keyboard is visible and when not).
Related
I need to create a menu with 20 vertical Rectangles in LibGdx.
The height of the rectangles is the entire height of the device.
The width of the rectangles is a set 20.0f
I have: private Stage stage; to which I intend to add on to my Rectangles.
The class is called LevelSelectScreen and implements Screen.
This is what I have so far:
public class LevelSelectScreen implements Screen {
private Stage stage;
private int stageNumber = 20;
Array<Rectangle> stageRectangles;
ShapeRenderer shapeRenderer;
public LevelSelectScreen(){
stage = new Stage();
stageRectangles = new Array<Rectangle>(stageNumber);
for(int i = 0;i<stageNumber;i++){
stageRectangles.get(i).setWidth(20f);
stageRectangles.get(i).setHeight(Gdx.graphics.getHeight());
stageRectangles.get(i).setPosition(new Vector2(20*i,0));
}
Gdx.graphics.getWidth();
shapeRenderer = new ShapeRenderer();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
//shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(0, 1, 0, 1);
for(int i = 0;i<stageNumber;i++){
Rectangle r = stageRectangles.get(i);
shapeRenderer.rect(r.x, r.y, r.getWidth(), r.getHeight());
}
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
Nothing appears and I don't think I'm using the Shape Renderer correctly.
How do I properly set up my scrollable rectangles?
Edit
Also, found this helpful link.
Varible class:
private Stage stage;
private int stageNumber = 20;
Array<Rectangle> stageRectangles;
ShapeRenderer shapeRenderer;
//new, for no magic number, but not required
private float w = 20f;
private float h = Gdx.graphics.getHeight();
private float space = 5;
private float xPos = w + space;
private float yPos = 0;
In your code:
public LevelSelectScreen(){
stage = new Stage();
stageRectangles = new Array<Rectangle>(stageNumber);
for(int i = 0; i<stageNumber; i++){
stageRectangles.add(new Rectangle(xPos * i,
yPos,
w,
h));
Gdx.app.log("Rectangle add", ""+i);
}
shapeRenderer = new ShapeRenderer();
}
you say that does not work or that I understand, but you're not having a Nullpointer or BoundsException ? anyway grabbing a few adjustments to your code this is what I have, it's what you wanted.
PS: do not would be more comfortable using a scroll and a table for when you have to use the listener, pictures ect, but it's just an idea, I hope you have understood what you were saying
in your code:
for(int i = 0; i<stageNumber; i++){
stageRectangles.get(i).setWidth(20f);
stageRectangles.get(i).setHeight(Gdx.graphics.getHeight());
stageRectangles.get(i).setPosition(new Vector2(25*i,0));
}
.
in this point stageRectangles.get(i).setWidth(20f);
the size is 0, then the array has an initial capacity
of 20 but is empty.
not getting something like this?
IndexOutOfBoundsException: index can't be >= size 0 >= 0
I need to make a credits screen (Activity) in my game. It would be just a vertically scrolling text lines without any images. Scrolling is to be performed automatically and no user interaction is allowed. Just like movie credits that goes from bottom to top. After the last text line has disappeared above top of the screen, it should restart.
How do I do it? It is sufficient to just use TextView and animate it somehow? Or should I put that TextView into ScrollView? What would you suggest?
I am using this :-
/**
* A TextView that scrolls it contents across the screen, in a similar fashion as movie credits roll
* across the theater screen.
*
* #author Matthias Kaeppler
*/
public class ScrollingTextView extends TextView implements Runnable {
private static final float DEFAULT_SPEED = 15.0f;
private Scroller scroller;
private float speed = DEFAULT_SPEED;
private boolean continuousScrolling = true;
public ScrollingTextView(Context context) {
super(context);
setup(context);
}
public ScrollingTextView(Context context, AttributeSet attributes) {
super(context, attributes);
setup(context);
}
private void setup(Context context) {
scroller = new Scroller(context, new LinearInterpolator());
setScroller(scroller);
}
#Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (scroller.isFinished()) {
scroll();
}
}
private void scroll() {
int viewHeight = getHeight();
int visibleHeight = viewHeight - getPaddingBottom() - getPaddingTop();
int lineHeight = getLineHeight();
int offset = -1 * visibleHeight;
int totallineHeight = getLineCount() * lineHeight;
int distance = totallineHeight + visibleHeight;
int duration = (int) (distance * speed);
if (totallineHeight > visibleHeight) {
scroller.startScroll(0, offset, 0, distance, duration);
if (continuousScrolling) {
post(this);
}
}
}
#Override
public void run() {
if (scroller.isFinished()) {
scroll();
} else {
post(this);
}
}
public void setSpeed(float speed) {
this.speed = speed;
}
public float getSpeed() {
return speed;
}
public void setContinuousScrolling(boolean continuousScrolling) {
this.continuousScrolling = continuousScrolling;
}
public boolean isContinuousScrolling() {
return continuousScrolling;
}
}
I have a ScrollPane that has multiple images horizontally aligned in a Group. What I need is scroll horizontally in a way to "snap" to images when scrolling & not just scroll to any amount needed. So after any swiping, the scrolling should stop to fit a whole image & not half an image. Mainly each image width is equal to the scrollpane width.
Any idea how to achieve this with libgdx ScrollPane?
Here's a sample code:
Image imgWhite = new Image(white);
imgWhite.setSize(width, height);
imgWhite.setPosition(0, 0);
Image imgYellow = new Image(white);
imgYellow.setColor(Color.YELLOW);
imgYellow.setSize(width, height);
imgYellow.setPosition(width, 0);
Image imgGreen = new Image(white);
imgGreen.setColor(Color.GREEN);
imgGreen.setSize(width, height);
imgGreen.setPosition(2*width, 0);
Group grp = new Group();
grp.addActor(imgWhite);
grp.addActor(imgGreen);
grp.addActor(imgYellow);
grp.setSize(3*width, height);
ScrollPane scrollPane = new ScrollPane(grp);
scrollPane.setSize(width, height);
Use PagedScrollPane (call addPage to add your images):
package com.your.package;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.utils.Array;
import com.esotericsoftware.tablelayout.Cell;
public class PagedScrollPane extends ScrollPane {
private boolean wasPanDragFling = false;
public static interface ScrollRunnable
{
public void run(Actor scrolledTo);
}
private Table content;
private float pageSpace;
private ScrollRunnable onScroll;
public PagedScrollPane (float pageSpace) {
super(null);
setup(pageSpace);
}
public PagedScrollPane (Skin skin, float pageSpace) {
super(null, skin);
setup(pageSpace);
}
public PagedScrollPane (Skin skin, String styleName, float pageSpace) {
super(null, skin, styleName);
setup(pageSpace);
}
public PagedScrollPane (Actor widget, ScrollPaneStyle style, float pageSpace) {
super(null, style);
setup(pageSpace);
}
public void setOnScroll(ScrollRunnable onScroll)
{
this.onScroll = onScroll;
}
private void setup(float pageSpace) {
this.pageSpace = pageSpace;
this.onScroll = null;
content = new Table();
content.defaults().space(pageSpace);
super.setWidget(content);
}
public void addPages (Actor... pages) {
for (Actor page : pages) {
content.add(page).expandY().fillY();
}
}
public Cell addPage (Actor page) {
return content.add(page).expandY().fillY();
}
#Override
public void act (float delta) {
super.act(delta);
if (wasPanDragFling && !isPanning() && !isDragging() && !isFlinging()) {
wasPanDragFling = false;
scrollToPage();
} else {
if (isPanning() || isDragging() || isFlinging()) {
wasPanDragFling = true;
}
}
}
#Override
public void setWidget (Actor widget)
{
//
}
public void setPageSpacing (float pageSpacing) {
if (content != null) {
content.defaults().space(pageSpacing);
for (#SuppressWarnings("rawtypes") Cell cell : content.getCells()) {
cell.space(pageSpacing);
}
content.invalidate();
}
}
private void scrollToPage () {
final float width = getWidth();
final float scrollX = getScrollX() + getWidth() / 2f;
Array<Actor> pages = content.getChildren();
if (pages.size > 0) {
for (Actor a : pages) {
float pageX = a.getX();
float pageWidth = a.getWidth();
if (scrollX >= pageX - pageWidth && scrollX < pageX + pageWidth)
{
setScrollX(pageX - (width - pageWidth) / 2f);
if (onScroll != null)
{
onScroll.run(a);
}
break;
}
}
}
}
public void scrollTo(Actor listenerActor)
{
float pageX = listenerActor.getX();
float pageWidth = listenerActor.getWidth();
final float width = getWidth();
setScrollX(pageX - (width - pageWidth) / 2f);
}
public void addEmptyPage(float offset)
{
content.add().minWidth(offset);
}
}
Also, it have setOnScroll method that allows to set callback after scroll your pane to some image.
Edit: Modified the condition in scrollToPage() method to avoid blindspot points (where scroll never snaps to a page).
Hi I am using the Gallery widget to show images downloaded from the internet.
to show several images and I would like to have a gradual zoom while people slide up and down on the screen. I know how to implement the touch event the only thing I don't know how to make the whole gallery view grow gradually. I don't want to zoom in on one image I want the whole gallery to zoom in/out gradually.
EDIT3: I manage to zoom the visible part of the gallery but the problem is I need to find a way for the gallery to find out about it and update it's other children too.
What happens is if 3 images are visible then you start zooming and the gallery does get smaller, so do the images but what I would like in this case is more images to be visible but I don't know how to reach this desired effect. Here's the entire code:
public class Gallery1 extends Activity implements OnTouchListener {
private static final String TAG = "GalleryTest";
private float zoom=0.0f;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
Gallery g;
LinearLayout layout2;
private ImageAdapter ad;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery_1);
layout2=(LinearLayout) findViewById(R.id.layout2);
// Reference the Gallery view
g = (Gallery) findViewById(R.id.gallery);
// Set the adapter to our custom adapter (below)
ad=new ImageAdapter(this);
g.setAdapter(ad);
layout2.setOnTouchListener(this);
}
public void zoomList(boolean increase) {
Log.i(TAG, "startig animation");
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(g, "scaleX", zoom),
ObjectAnimator.ofFloat(g, "scaleY", zoom)
);
set.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
set.setDuration(100).start();
}
public class ImageAdapter extends BaseAdapter {
private static final int ITEM_WIDTH = 136;
private static final int ITEM_HEIGHT = 88;
private final int mGalleryItemBackground;
private final Context mContext;
private final Integer[] mImageIds = {
R.drawable.gallery_photo_1,
R.drawable.gallery_photo_2,
R.drawable.gallery_photo_3,
R.drawable.gallery_photo_4,
R.drawable.gallery_photo_5,
R.drawable.gallery_photo_6,
R.drawable.gallery_photo_7,
R.drawable.gallery_photo_8
};
private final float mDensity;
public ImageAdapter(Context c) {
mContext = c;
// See res/values/attrs.xml for the <declare-styleable> that defines
// Gallery1.
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
mGalleryItemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 1);
a.recycle();
mDensity = c.getResources().getDisplayMetrics().density;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
convertView = new ImageView(mContext);
imageView = (ImageView) convertView;
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setLayoutParams(new Gallery.LayoutParams(
(int) (ITEM_WIDTH * mDensity + 0.5f),
(int) (ITEM_HEIGHT * mDensity + 0.5f)));
} else {
imageView = (ImageView) convertView;
}
imageView.setImageResource(mImageIds[position]);
return imageView;
}
}
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE
&& event.getPointerCount() > 1) {
midPoint(mid, event);
if(mid.y > start.y){
Log.i(TAG, "Going down (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); // going down so increase
if ((Math.abs(mid.y - start.y) > 10) && (zoom<2.5f)){
zoom=zoom+0.1f;
midPoint(start, event);
zoomList(true);
}
return true;
}else if(mid.y < start.y){
Log.i(TAG, "Going up (Math.abs(mid.y - start.y)= "+(Math.abs(mid.y - start.y))+" and zoom="+zoom); //smaller
if ((Math.abs(mid.y - start.y) > 10) &&(zoom>0.1)){
midPoint(start, event);
zoom=zoom-0.1f;
zoomList(false);
}
return true;
}
}
else if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN) {
Log.e(TAG, "Pointer went down: " + event.getPointerCount());
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
Log.i(TAG, "Pointer going up");
return true;
}
else if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.i(TAG, "Pointer going down");
start.set(event.getX(), event.getY());
return true;
}
return false;
// indicate event was handled or not
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
I realise I will probably have to extend the Gallery or even another View group or create my own class but I don't know where to start: which method use the one responsible for scaling...
EDIT4: I don't know if he question is clear enough. Here is an example of states:
State one: initial state, we have 3 images in view
State 2: we detect vertical touches going up with 2 fingers = we have to zoom out
state 3: we start zooming = animation on the gallery or on the children???
state 4: gallery detects that it's 3 children are smaller
state 5: gallery adds 1 /more children according to the new available space
LAST UPDATE:
Thanks to all that have posted but I have finally reached a conclusion and that is to not use Gallery at all:
1. It's deprecated
2. It's not customizable enough for my case
If you want to animate several images at once you may want to consider using OpenGl, I am using libgdx library:
https://github.com/libgdx/libgdx
The following ScalingGallery implementation might be of help.
This gallery subclass overrides the getChildStaticTransformation(View child, Transformation t) method in which the scaling is performed. You can further customize the scaling parameters to fit your own needs.
Please note the ScalingGalleryItemLayout.java class. This is necessary because after you have performed the scaling operationg on the child views, their hit boxes are no longer valid so they must be updated from with the getChildStaticTransformation(View child, Transformation t) method.
This is done by wrapping each gallery item in a ScalingGalleryItemLayout which extends a LinearLayout. Again, you can customize this to fit your own needs if a LinearLayout does not meet your needs for layout out your gallery items.
File : /src/com/example/ScalingGallery.java
/**
* A Customized Gallery component which alters the size and position of its items based on their position in the Gallery.
*/
public class ScalingGallery extends Gallery {
public static final int ITEM_SPACING = -20;
private static final float SIZE_SCALE_MULTIPLIER = 0.25f;
private static final float ALPHA_SCALE_MULTIPLIER = 0.5f;
private static final float X_OFFSET = 20.0f;
/**
* Implemented by child view to adjust the boundaries after it has been matrix transformed.
*/
public interface SetHitRectInterface {
public void setHitRect(RectF newRect);
}
/**
* #param context
* Context that this Gallery will be used in.
* #param attrs
* Attributes for this Gallery (via either xml or in-code)
*/
public ScalingGallery(Context context, AttributeSet attrs) {
super(context, attrs);
setStaticTransformationsEnabled(true);
setChildrenDrawingOrderEnabled(true);
}
/**
* {#inheritDoc}
*
* #see #setStaticTransformationsEnabled(boolean)
*
* This is where the scaling happens.
*/
protected boolean getChildStaticTransformation(View child, Transformation t) {
child.invalidate();
t.clear();
t.setTransformationType(Transformation.TYPE_BOTH);
// Position of the child in the Gallery (... +2 +1 0 -1 -2 ... 0 being the middle)
final int childPosition = getSelectedItemPosition() - getPositionForView(child);
final int childPositionAbs = (int) Math.abs(childPosition);
final float left = child.getLeft();
final float top = child.getTop();
final float right = child.getRight();
final float bottom = child.getBottom();
Matrix matrix = t.getMatrix();
RectF modifiedHitBox = new RectF();
// Change alpha, scale and translate non-middle child views.
if (childPosition != 0) {
final int height = child.getMeasuredHeight();
final int width = child.getMeasuredWidth();
// Scale the size.
float scaledSize = 1.0f - (childPositionAbs * SIZE_SCALE_MULTIPLIER);
if (scaledSize < 0) {
scaledSize = 0;
}
matrix.setScale(scaledSize, scaledSize);
float moveX = 0;
float moveY = 0;
// Moving from right to left -- linear move since the scaling is done with respect to top-left corner of the view.
if (childPosition < 0) {
moveX = ((childPositionAbs - 1) * SIZE_SCALE_MULTIPLIER * width) + X_OFFSET;
moveX *= -1;
} else { // Moving from left to right -- sum of the previous positions' x displacements.
// X(n) = X(0) + X(1) + X(2) + ... + X(n-1)
for (int i = childPositionAbs; i > 0; i--) {
moveX += (i * SIZE_SCALE_MULTIPLIER * width);
}
moveX += X_OFFSET;
}
// Moving down y-axis is linear.
moveY = ((childPositionAbs * SIZE_SCALE_MULTIPLIER * height) / 2);
matrix.postTranslate(moveX, moveY);
// Scale alpha value.
final float alpha = (1.0f / childPositionAbs) * ALPHA_SCALE_MULTIPLIER;
t.setAlpha(alpha);
// Calculate new hit box. Since we moved the child, the hitbox is no longer lined up with the new child position.
final float newLeft = left + moveX;
final float newTop = top + moveY;
final float newRight = newLeft + (width * scaledSize);
final float newBottom = newTop + (height * scaledSize);
modifiedHitBox = new RectF(newLeft, newTop, newRight, newBottom);
} else {
modifiedHitBox = new RectF(left, top, right, bottom);
}
// update child hit box so you can tap within the child's boundary
((SetHitRectInterface) child).setHitRect(modifiedHitBox);
return true;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// Helps to smooth out jittering during scrolling.
// read more - http://www.unwesen.de/2011/04/17/android-jittery-scrolling-gallery/
final int viewsOnScreen = getLastVisiblePosition() - getFirstVisiblePosition();
if (viewsOnScreen <= 0) {
super.onLayout(changed, l, t, r, b);
}
}
private int mLastDrawnPosition;
#Override
protected int getChildDrawingOrder(int childCount, int i) {
//Reset the last position variable every time we are starting a new drawing loop
if (i == 0) {
mLastDrawnPosition = 0;
}
final int centerPosition = getSelectedItemPosition() - getFirstVisiblePosition();
if (i == childCount - 1) {
return centerPosition;
} else if (i >= centerPosition) {
mLastDrawnPosition++;
return childCount - mLastDrawnPosition;
} else {
return i;
}
}
}
File : /src/com/example/ScalingGalleryItemLayout.java
public class ScalingGalleryItemLayout extends LinearLayout implements SetHitRectInterface {
public ScalingGalleryItemLayout(Context context) {
super(context);
}
public ScalingGalleryItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScalingGalleryItemLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private Rect mTransformedRect;
#Override
public void setHitRect(RectF newRect) {
if (newRect == null) {
return;
}
if (mTransformedRect == null) {
mTransformedRect = new Rect();
}
newRect.round(mTransformedRect);
}
#Override
public void getHitRect(Rect outRect) {
if (mTransformedRect == null) {
super.getHitRect(outRect);
} else {
outRect.set(mTransformedRect);
}
}
}
File : /res/layout/ScaledGalleryItemLayout.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.ScalingGalleryItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gallery_item_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:padding="5dp" >
<ImageView
android:id="#+id/gallery_item_image"
android:layout_width="360px"
android:layout_height="210px"
android:layout_gravity="center"
android:antialias="true"
android:background="#drawable/gallery_item_button_selector"
android:cropToPadding="true"
android:padding="35dp"
android:scaleType="centerInside" />
<TextView
android:id="#+id/gallery_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#drawable/white"
android:textSize="30sp" />
</com.example.ScalingGalleryItemLayout>
To keep the state of the animation after it is done, just do this on your animation:
youranim.setFillAfter(true);
Edit :
In my project, I use this method and i think, it's help you :
http://developer.sonymobile.com/wp/2011/04/12/how-to-take-advantage-of-the-pinch-to-zoom-feature-in-your-xperia%E2%84%A2-10-apps-part-1/
U can do Image Zoom pinch option for gallery also.
by using below code lines:
you can download the example.
https://github.com/alvinsj/android-image-gallery/downloads
I hope this example will help to u..if u have any queries ask me.....
This is solution
integrate gallery component in android with gesture-image library
gesture-imageView
And here is full sample code
SampleCode
I couldn't find a good example for how to do this.
I have a RelativeLayout set with x height.
I want to add a button which expands the height to x+y height.
can someone refer me to a good example on how to do it programmatically?
You marked the solution that was closest. This is the exact solution. I had the same problem. Hopefully this answer will help others.
InstantiateResizeAnimation
ResizeAnimation resizeAnimation = new ResizeAnimation(
view,
targetHeight,
startHeight
);
resizeAnimation.setDuration(duration);
view.startAnimation(resizeAnimation);
ResizeAnimation class should look like this
public class ResizeAnimation extends Animation {
final int targetHeight;
View view;
int startHeight;
public ResizeAnimation(View view, int targetHeight, int startHeight) {
this.view = view;
this.targetHeight = targetHeight;
this.startHeight = startHeight;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
int newHeight = (int) (startHeight + targetHeight * interpolatedTime);
//to support decent animation, change new heigt as Nico S. recommended in comments
//int newHeight = (int) (startHeight+(targetHeight - startHeight) * interpolatedTime);
view.getLayoutParams().height = newHeight;
view.requestLayout();
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
You need a scale animation here is the official documentation
this is in code
private void animate() {
ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
ScaleAnimation scale = new ScaleAnimation((float)1.0, (float)1.5, (float)1.0, (float)1.5);
scale.setFillAfter(true);
scale.setDuration(500);
imageView.startAnimation(scale);
}
Please check below new edited answer as below. But here you need to know the exact new height.
public class LayoutAnimationActivity extends Activity {
RelativeLayout ril1;
Button btn;
int initialHeight;
int actualHeight;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
ril1 = (RelativeLayout) findViewById(R.id.relativeLayout1);
btn = new Button(this);
btn.setWidth(100);
btn.setHeight(200);
btn.setText("Button");
actualHeight = 210;
Ani a = new Ani();
a.setDuration(2000);
ril1.startAnimation(a);
}
class Ani extends Animation {
public Ani() {}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
int newHeight;
newHeight = (int) (initialHeight * interpolatedTime);
ril1.removeAllViews();
btn.setWidth(100);
btn.setHeight(300);
btn.setText("as");
ril1.addView(btn);
ril1.getLayoutParams().height = newHeight;
ril1.requestLayout();
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
initialHeight = actualHeight;
}
#Override
public boolean willChangeBounds() {
return true;
}
};
}
Two simple ways to do this without an Animation class:
1) Set android:animateLayoutChanges="true" in you xml layout file
2) Use a ViewProperty animator
layout.setPivot(0);
layout.animate().scaleY(scaleFactor).setDuration(500);
The pivot tells the view where to scale from, default is in the middle, which in my experience is almost never what you want. The duration is optional (default = 1000).
final Button button1 = (Button) view.findViewById(R.id.button);
final CollapseAnimator animator = new CollapseAnimator(topLayout);
final ViewTreeObserver.OnGlobalLayoutListener listener = new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int mHeight = button1.getMeasuredHeight();
KLog.i("onGlobalLayout() mHeight:" + mHeight);
animator.setValues(mHeight*2, mHeight);
}
};
button1.getViewTreeObserver().addOnGlobalLayoutListener(listener);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
view.post(new Runnable() {
#Override
public void run() {
button1.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
animator.collapse();
}
});
}
});
and class
public class CollapseAnimator {
private View view;
private boolean collapse=true;
private int duation=300;
private int destHeight=300;
private ValueAnimator animator;
private int originHeight=0;
private int from=0;
private int to=0;
public CollapseAnimator(View view ) {
this.view = view;
}
public void setValues(int destHeight,int originHeight){
this.destHeight = destHeight;
this.originHeight=originHeight;
from=originHeight;
to=originHeight;
}
public void collapse(){
from=to;
if(collapse){
to=destHeight;
collapse=false;
}else{
to=originHeight;
collapse=true;
}
KLog.i("from:" + from+",to:"+to);
animator = ValueAnimator.ofInt(from, to);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = val;
view.setLayoutParams(layoutParams);
}
});
animator.setDuration(duation);
animator.start();
}
}