android: setting a button programmatically using setX and setY - android

public class Game_collecting_view extends View
{
Button image_boy;
private static final int BOY_DIAMETER = 200; // initial spot size
int boy_width =0;
int boy_height =0;
public void setGame_collecting(Game_collecting mGame_collecting)
{
this.mGame_collecting = mGame_collecting;
}
// constructs a new View
public Game_collecting_view(Context context, RelativeLayout parentLayout)
{
super(context);
resources = context.getResources(); // save Resources for loading external values
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// get references to various GUI components
relativeLayout = parentLayout;
spotHandler = new Handler(); // used to add spots when game starts
}
#Override
protected void onSizeChanged(int width, int height, int oldw, int oldh)
{
viewWidth = width; // save the new width
viewHeight = height; // save the new height
}
public void set_boy()
{
final Button boy = (Button) layoutInflater.inflate(R.layout.untouched, null);
boy.setX(viewWidth /2);
boy.setY(viewHeight - BOY_DIAMETER);
boy.setPadding(0,0,0,0);
boy.setBackgroundResource(R.drawable.blue);
boy.setLayoutParams(new RelativeLayout.LayoutParams(BOY_DIAMETER, BOY_DIAMETER));
relativeLayout.addView(boy); // add spot to the screen
Toast.makeText(getContext(), "set_boy\nviewWidth=" +viewHeight +"\nviewHeight=" +viewHeight, Toast.LENGTH_SHORT).show();
boy.setOnClickListener
(
new OnClickListener()
{
public void onClick(View v)
{
touchedSpot(boy);
}
}
);
}
public void resume(Context context)
{
resetGame();
}
public void resetGame()
{
for (int i = 1; i <= INITIAL_SPOTS; ++i)
{
spotHandler.postDelayed(addSpotRunnable, i * SPOT_DELAY);
generate_text();
}
set_boy();
}
private Runnable addSpotRunnable = new Runnable()
{
public void run()
{
addNewSpot(); // add a new spot to the game
}
};
Objective:
I would like to set the boy icon at the bottom middle of the screen.
The boy icon is set at this way for later dynamic interface (swipe the screen to the right the boy icon will move to the right, vice versa)
Observation:
The toast reports both the viewWidth and viewHeight =0, and the boy icon appears at 0,0 (left upper corner). If I set the setY(viewHeight + BOY_DIAMETER), the boy icon will be located at (0, 200).
Question:
I would like to ask why the viewWidth and viewHeight both report 0. How could the onSizeChanged be called immediately such that the boy icone could be set at the bottom center of the screen?
Thanks!!

The location is null until Android has calculated their positions. You can retrieve the height and width like this:
image_boy.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int height = image_boy.getHeight();
int width = image_boy.getWidth();
//these values won't be null
}
});

set layout param for setting the view position

Related

How to blur the background image of the main layout in android?

I just want to make the background image to look blur(like defocus),I used alpha but it was not only setting alpha to my background image but also to the whole content...Is there any way that I can set blur effect only to my background image!!!..
need help thanks in advance!!..
Please use below tutorial for blur background
NavigationDrawer :
https://github.com/charbgr/BlurNavigationDrawer
Fragment:
https://github.com/tvbarthel/BlurDialogFragment
Image : If you want to blur an image in layout :
https://github.com/kikoso/android-stackblur
Layout:
https://github.com/PomepuyN/BlurEffectForAndroidDesign
public class MainActivity extends Activity {
private static final String BLURRED_IMG_PATH = "blurred_image.png";
private static final int TOP_HEIGHT = 700;
private ListView mList;
private ImageView mBlurredImage;
private View headerView;
private ImageView mNormalImage;
private ScrollableImageView mBlurredImageHeader;
private Switch mSwitch;
private float alpha;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
// Get the screen width
final int screenWidth = ImageUtils.getScreenWidth(this);
// Find the view
mBlurredImage = (ImageView) findViewById(R.id.blurred_image);
mNormalImage = (ImageView) findViewById(R.id.normal_image);
mBlurredImageHeader = (ScrollableImageView) findViewById(R.id.blurred_image_header);
mSwitch = (Switch) findViewById(R.id.background_switch);
mList = (ListView) findViewById(R.id.list);
// prepare the header ScrollableImageView
mBlurredImageHeader.setScreenWidth(screenWidth);
// Action for the switch
mSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mBlurredImage.setAlpha(alpha);
} else {
mBlurredImage.setAlpha(0f);
}
}
});
// Try to find the blurred image
final File blurredImage = new File(getFilesDir() + BLURRED_IMG_PATH);
if (!blurredImage.exists()) {
// launch the progressbar in ActionBar
setProgressBarIndeterminateVisibility(true);
new Thread(new Runnable() {
#Override
public void run() {
// No image found => let's generate it!
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.image, options);
Bitmap newImg = Blur.fastblur(MainActivity.this, image, 12);
ImageUtils.storeImage(newImg, blurredImage);
runOnUiThread(new Runnable() {
#Override
public void run() {
updateView(screenWidth);
// And finally stop the progressbar
setProgressBarIndeterminateVisibility(false);
}
});
}
}).start();
} else {
// The image has been found. Let's update the view
updateView(screenWidth);
}
String[] strings = getResources().getStringArray(R.array.list_content);
// Prepare the header view for our list
headerView = new View(this);
headerView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, TOP_HEIGHT));
mList.addHeaderView(headerView);
mList.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, strings));
mList.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
/**
* Listen to the list scroll. This is where magic happens ;)
*/
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// Calculate the ratio between the scroll amount and the list
// header weight to determinate the top picture alpha
alpha = (float) -headerView.getTop() / (float) TOP_HEIGHT;
// Apply a ceil
if (alpha > 1) {
alpha = 1;
}
// Apply on the ImageView if needed
if (mSwitch.isChecked()) {
mBlurredImage.setAlpha(alpha);
}
// Parallax effect : we apply half the scroll amount to our
// three views
mBlurredImage.setTop(headerView.getTop() / 2);
mNormalImage.setTop(headerView.getTop() / 2);
mBlurredImageHeader.handleScroll(headerView.getTop() / 2);
}
});
}
private void updateView(final int screenWidth) {
Bitmap bmpBlurred = BitmapFactory.decodeFile(getFilesDir() + BLURRED_IMG_PATH);
bmpBlurred = Bitmap.createScaledBitmap(bmpBlurred, screenWidth, (int) (bmpBlurred.getHeight()
* ((float) screenWidth) / (float) bmpBlurred.getWidth()), false);
mBlurredImage.setImageBitmap(bmpBlurred);
mBlurredImageHeader.setoriginalImage(bmpBlurred);
}
}
Kotlin code, use view effect Library :
1- Add library in build.gradle:
implementation 'com.github.mirrajabi:view-effects:e355a1bac4'
2- Blure the background of root view or view, here Constraint Layout blured by 20%
ViewFilter.getInstance(this)
.setRenderer( BlurRenderer(20))
.applyFilterOnView( root_constraintLayout,
root_constraintLayout )
my github repository for blur background : link

How to rotate an ImageView, not just the image, programmatically

I need to rotate an ImageView using an animation, so that the width and height of the ImageView also change.
I have tried using ViewPropertyAnimator, using View.animate but this just rotates the image, and not the actual view itself.
I need to use this so I can work out the x and y coords of the view after it has been rotated, and also the width and height of it.
I have made a test app to just rotate a card image, and I have taken pictures with the layouts visible to show what I mean.
As you can see in the code, I've also tried to force change the width and height in a runnable after the animation has finished, but this doesn't work. Nor does using scaleX/scaleY to try and change things.
public class MyActivity extends Activity implements View.OnClickListener{
RelativeLayout temp;
ImageView card;
int rotation = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
card = (ImageView) findViewById(R.id.card);
card.setOnClickListener(this);
}
#Override
public void onClick(final View v) {
final Runnable e1 = new Runnable() {
public void run() {
Toast.makeText(MyActivity.this, "After1 w="+v.getMeasuredWidth()+" h="+v.getMeasuredHeight(), Toast.LENGTH_SHORT).show();
int w = v.getMeasuredWidth();
int h = v.getMeasuredHeight();
v.getLayoutParams().width = h;
v.getLayoutParams().height = w;
v.setLayoutParams(v.getLayoutParams());
Toast.makeText(MyActivity.this, "After2 w="+v.getMeasuredWidth()+" h="+v.getMeasuredHeight(), Toast.LENGTH_SHORT).show();
}
};
int[] cardCoords = new int[2];
v.getLocationOnScreen(cardCoords);
Toast.makeText(MyActivity.this, "x="+cardCoords[0]+" y="+cardCoords[1], Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Before w="+v.getMeasuredWidth()+" h="+v.getMeasuredHeight(), Toast.LENGTH_SHORT).show();
rotation = rotation + 90;
v.animate().
setDuration(1000).
rotationBy(90);
//scaleX((float) v.getMeasuredHeight() / (float) v.getMeasuredWidth()).
//scaleY((float) v.getMeasuredHeight() / (float) v.getMeasuredWidth()).
//.withEndAction(e1);
}
}
You should be looking to rotate a view, not the image then.
Rotating a view in Android

Android: How to make a gridview of equal proportions within the Java code

I am working on an application which has a main screen with a gridview layout.
As it stands currently, I am hardcoding in DP numbers for the height and width of the boxes, which I obviously do not want to do. How to I create code that will determine the users' screen size and match the boxes accordingly so that someone with a large phone like a note will view the same thing as someone on a droid mini? IE, when hardcoding to 500dp on each side, it looks like this:
But my goal is to make it look like this on every screen size:
Currently, this is the Java code I have:
public class ActivityAdapter extends BaseAdapter {
//Array of Icons that will be used as menu choices
public static int[] imageOptions = {
R.drawable.vacation_quota, //Position 0
R.drawable.revenue_deficit, //Position 1
//+ many more options...
};
private Context context;
//Constructor to pass context back to Main class
public ActivityAdapter(Context applicationContext) {
context = applicationContext;
}
//Number of elements to be displayed on the grid
#Override
public int getCount() {
return imageOptions.length;
}
#Override
public View getView(int position, View convertView, ViewGroup arg2) {
ImageView iv;
if(convertView != null){
iv = (ImageView) convertView;
} else {
iv = new ImageView(context);
//Here I have it hard coded to match a 480px width. Here is where I need to change it, just not sure how
iv.setLayoutParams(new GridView.LayoutParams(240, 240));
iv.setScaleType(ScaleType.CENTER_CROP); //Center the cropping
}
//Sets the image to correspond to its position within the array.
iv.setImageResource(imageOptions[position]);
return iv;
}
Any ideas? I think logically I want to figure out the screen dimensions and use them to make the image dimensions match, just not sure how. Research from other threads has not helped a great deal so hoping I can get a simpler answer here with code posting.
You should get the screen width and height. Then use these values to dynamically set height and width for each cell
Try this code-
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle state) {
setContentView(new ViewGroup(this) {
private RelativeLayout[] items = new RelativeLayout[9];
private int width, height, itemWidth, itemHeight;
{
Random r = new Random();
for (int i = 0; i < 9; i++) {
items[i] = new RelativeLayout(getContext());
float[] hsv = new float[] {360 * r.nextFloat(), .50f, .75f};
items[i].setBackgroundColor(Color.HSVToColor(hsv));
addView(items[i]);
// UPDATE ////////////////////////////////////
ImageView image = new ImageView(getContext());
switch (i) {
case 0: // top left
case 1: // top center
case 2: // top right
case 3: // center left
case 4: // center center
case 5: // center right
case 6: // bottom left
case 7: // bottom center
case 8: // bottom right
image.setImageResource(R.drawable.ic_launcher);
break;
}
image.setScaleType(ScaleType.FIT_XY);
image.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT
));
items[i].addView(image);
//////////////////////////////////////////////
}
}
#Override
protected void onMeasure(int wMS, int hMS) {
width = MeasureSpec.getSize(wMS);
height = MeasureSpec.getSize(hMS);
itemWidth = width / 3;
itemHeight = height / 3;
wMS = MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY);
hMS = MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY);
measureChildren(wMS, hMS);
setMeasuredDimension(width, height);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < 9; i++) {
l = itemWidth * (i % 3);
t = itemHeight * (i / 3);
r = l + itemWidth;
b = t + itemHeight;
items[i].layout(l, t, r, b);
}
}
});
super.onCreate(state);
}
}
Output-
Edit-
For creating scrollable grid view see this http://www.androidhive.info/2012/02/android-gridview-layout-tutorial/
I ended up not able to use some of the recommendations here and had to use a deprecated method to retain my app structure. The code specifically that was added to mine was:
iv = new ImageView(context);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
float width2 = display.getWidth();
int length = (int) (width2/2);
iv.setLayoutParams(new GridView.LayoutParams(length, length));
With this, the height and width would crop to the right size depending on the size of the screen.

Best way to animate rectangle in Android

I want to animate a rectangle filled with one opaque color. The attributes I will be animating is the translation, and the width of the active menu item.
I know how to animate things, but in this case, I want it to do no layouts on the view, since my animation will occur inside a LinearLayout, and it will not exceed it's size.
The Blue line on top of my layout is what I will be animating. It will go horizontally to the left and right, while changing it's width, so that it fits on the selected menu item.
I usually work with animations on the margin, but it consumes a lot of processing to re-calculate bounds on the layout process.
Any suggestions on how to do that?
That depends entirely on what API level you're targetting, if you're only targeting >3.0 then ObjectAnimator and ValueAnimator or the nicer ViewPropertyAnimator are your best friend, they let you do simple things like "move the X value of this 100dp while increasing the width by a factor of two, in 300ms".
If you're targeting a lower API level check out NineOldAndroids which brings that functionality over to all versions of Android.
To do what you want to do it'd be something along the lines of:
myImageView.scaleXBy(FACTOR_NEEDED_FOR_NEW_WIDTH);
and that's all to it.
As a sidenote: It looks like you might be attempting to replicate a ViewPager's indicator, in which case you should be using an actual indicator.
I had to animate the Margin and the Width of the view, because there was no way out, since I'm using android version >=8.
Here is my two classes that can do this:
MarginAnimation class:
public class MarginAnimation extends Animation{// implements AnimationListener{
public static String TAG = "MarginAnimation";
protected View animatingView;
protected int fromMarginLeft = 0;
protected int fromMarginTop = 0;
protected int toMarginLeft = 0;
protected int toMarginTop = 0;
protected LayoutParams layoutParam;
public MarginAnimation(View v, int toMarginLeft, int toMarginTop) {
this.toMarginLeft = toMarginLeft;
this.toMarginTop = toMarginTop;
this.animatingView = v;
// Save layout param
layoutParam = (LayoutParams) animatingView.getLayoutParams();
// Save current margins as initial state
saveCurrent();
// Set the listner to be self object
// setAnimationListener(this);
}
public MarginAnimation(View v, int fromMarginLeft, int toMarginLeft, int fromMarginTop, int toMarginTop) {
this.fromMarginLeft = fromMarginLeft;
this.toMarginLeft = toMarginLeft;
this.fromMarginTop = fromMarginTop;
this.toMarginTop = toMarginTop;
this.animatingView = v;
// Save layout param
layoutParam = (LayoutParams) animatingView.getLayoutParams();
// Set the listner to be self object
// setAnimationListener(this);
}
protected void saveCurrent(){
fromMarginLeft = layoutParam.leftMargin;
fromMarginTop = layoutParam.topMargin;
}
long lastTime = 0;
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
// long thisTime = System.nanoTime();
// if(lastTime != 0)
// Log.e(TAG, ((thisTime - lastTime) / 1000) + "delta Anim.");
// lastTime = thisTime;
layoutParam.leftMargin = (int)(fromMarginLeft + (toMarginLeft - fromMarginLeft) * interpolatedTime);
layoutParam.topMargin = (int)(fromMarginTop + (toMarginTop- fromMarginTop) * interpolatedTime);
animatingView.setLayoutParams(layoutParam);
}
#Override
public boolean willChangeBounds() {
return false;
}
}
MarginAndWidthAnimation class:
public class MarginAndWidthAnimation extends MarginAnimation{
public static String TAG = "MarginAndWidthAnimation";
int toWidth;
int fromWidth;
public MarginAndWidthAnimation(View v, int toMarginLeft, int toMarginTop, int toWidth) {
super(v, toMarginLeft,toMarginTop);
this.toWidth = toWidth;
// Log.i(TAG, "++F: "+this.fromWidth+" T: "+this.toWidth);
}
protected void saveCurrent(){
super.saveCurrent();
// fromWidth = animatingView.getWidth();
fromWidth = layoutParam.width;
// Log.i(TAG, "F: "+fromWidth+" T: "+toWidth);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
layoutParam.width = (int)(fromWidth + (toWidth - fromWidth) * interpolatedTime);
// Log.i(TAG, "F: "+fromWidth+" T: "+toWidth+" S: "+layoutParam.width);
super.applyTransformation(interpolatedTime, t);
}
}

Animate view sliding out of another view, pushing views below out of the way

I have a list of buttons. When I press a button, a View should slide in a downwards motion out of the button, like this:
Start:
Halfway:
End:
How would I go about this? The View that should slide out is bigger than the button, so first hiding the View behind the button and then sliding it downwards causes the View to be visible above the button. That should not happen.
Any ideas or examples on how to approach this?
I believe the simplest approach is to extend Animation class and override applyTransformation() to change the view's height as follows:
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;
public class MyCustomAnimation extends Animation {
public final static int COLLAPSE = 1;
public final static int EXPAND = 0;
private View mView;
private int mEndHeight;
private int mType;
private LinearLayout.LayoutParams mLayoutParams;
public MyCustomAnimation(View view, int duration, int type) {
setDuration(duration);
mView = view;
mEndHeight = mView.getHeight();
mLayoutParams = ((LinearLayout.LayoutParams) view.getLayoutParams());
mType = type;
if(mType == EXPAND) {
mLayoutParams.height = 0;
} else {
mLayoutParams.height = LayoutParams.WRAP_CONTENT;
}
view.setVisibility(View.VISIBLE);
}
public int getHeight(){
return mView.getHeight();
}
public void setHeight(int height){
mEndHeight = height;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
if(mType == EXPAND) {
mLayoutParams.height = (int)(mEndHeight * interpolatedTime);
} else {
mLayoutParams.height = (int) (mEndHeight * (1 - interpolatedTime));
}
mView.requestLayout();
} else {
if(mType == EXPAND) {
mLayoutParams.height = LayoutParams.WRAP_CONTENT;
mView.requestLayout();
}else{
mView.setVisibility(View.GONE);
}
}
}
}
To use it, set your onclick() as follows:
int height;
#Override
public void onClick(View v) {
if(view2.getVisibility() == View.VISIBLE){
MyCustomAnimation a = new MyCustomAnimation(view2, 1000, MyCustomAnimation.COLLAPSE);
height = a.getHeight();
view2.startAnimation(a);
}else{
MyCustomAnimation a = new MyCustomAnimation(view2, 1000, MyCustomAnimation.EXPAND);
a.setHeight(height);
view2.startAnimation(a);
}
}
Regards.
Use something like:
Animation a = new ScaleAnimation(1, 1, 0, 1, Animation.RELATIVE_TO_SELF, (float) 0.5, Animation.RELATIVE_TO_SELF, (float) 0);
a.setFillAfter(true);
view.setAnimation(a);
a.setDuration(1000);
view.startAnimation(a);
Here is simple example of hand-made animation, that provide what you want. It works in test app, but I'm not sure that there is no bugs:
public class MainActivity extends Activity implements OnClickListener {
private Timer timer;
private TimerTask animationTask;
private View view1;
private View view2;
boolean animating;
boolean increasing = true;
int initHeight = -1;
private LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timer = new Timer();
view1 = findViewById(R.id.view1);// clickable view
view1.setOnClickListener(this);
view2 = findViewById(R.id.view2);// animated view
params = view2.getLayoutParams();
}
#Override
protected void onDestroy() {
super.onDestroy();
timer.cancel();
}
#Override
public void onClick(View v) {
Toast.makeText(this, "start animating...", Toast.LENGTH_SHORT).show();
animationTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (animationFinished()) {
animating = false;
cancel();//canceling animating task
return;
}
params.height += increasing ? 1 : -1;
view2.setLayoutParams(params);
}
});
}
private boolean animationFinished() {
int viewHeight = view2.getHeight();
if (increasing && viewHeight >= initHeight) {
return true;
}
if (!increasing && viewHeight <= 0) {
return true;
}
return false;
}
};
//if we already animating - we just change direction of animation
increasing = !increasing;
if (!animating) {
animating = true;
int height = view2.getHeight();
params.height = height;
view2.setLayoutParams(params);//change param "height" from "wrap_conent" to real height
if (initHeight < 0) {//height of view - we setup it only once
initHeight = height;
}
timer.schedule(animationTask, 0, 10);//changing repeat time here will fasten or slow down animation
}
}
}
Maybe you can set the height to 0 and gradually increase the height. But then you will have the problem that you have to be sure your text is aligned at the bottom of the view. And also to know what the maximal height of the view should be.
use a sliding list adapter so much easier than messing around with animations
https://github.com/tjerkw/Android-SlideExpandableListView
Simply pass android:animateLayoutChanges to LinearLayout that holds all the views, you will achieve your desired result.
I would do it like that. First the layout for the whole collapsible panel component: (pseudo xml)
RelativeLayout (id=panel, clip)
LinearLayout (id=content, alignParentBottom=true)
LinearLayout (id=handle, above=content)
This should ensure that the content is always below the handle.
Then when you need to collapse:
Animate the top margin of content from 0 to -content.height
Animate the height of the panel from current to current-content.height

Categories

Resources