Issue
My ConstraintLayout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp"
android:minWidth="0dp"
android:minHeight="0dp"
android:text="@string/start"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
My simplified code:
import android.annotation.SuppressLint;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
final Random rand = new Random();
private Button btn;
private float widthPixels, heightPixels;
private float minBtnSize, maxBtnSize;
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Obtaining screen's display properties. */
final DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
widthPixels = displaymetrics.widthPixels;
heightPixels = displaymetrics.heightPixels; // includes BotNavBar
heightPixels -= 162; // size of the "Virtual Nav Bar" at the bottom
float minDim = Math.min(widthPixels, heightPixels);
minBtnSize = minDim/25;
maxBtnSize = minDim/2;
/* Setting up the experiment's Button*/
btn = findViewById(R.id.btn);
btn.setOnTouchListener(new View.OnTouchListener(){
public boolean onTouch(View view, MotionEvent event){
/* Touch Events. */
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
/* Move and resize the button. */
launchNewAttempt(x, y);
break;
default:
break;
}
return true;
}
});
/* Setting up the beginning Button's state. */
init();
}
/**
* Initializing the Button shown at the very beginning.
*/
private void init() {
btn.setX(0);
btn.setY(0);
btn.setWidth((int)widthPixels);
btn.setHeight((int)heightPixels);
}
/**
* Called whenever the user releases the experiment's button (pressed "UP").
*/
private void launchNewAttempt() {
/* Random size for the "new" button. */
int size=(int)(minBtnSize+(maxBtnSize-minBtnSize)*rand.nextDouble());
btn.setWidth(size);
btn.setHeight(size);
/* Random position for the "new" button. */
float dx = rand.nextFloat() * (widthPixels - size);
float dy = rand.nextFloat() * (heightPixels - size);
btn.setX(dx);
btn.setY(dy);
}
}
Expected behavior:
A button that fills the whole screen appears at the beginning. Once pressed, that same button is resized (as a square, with sides at least 1/25 th and at most 1/2 of the width of the screen) and moved around the screen at random positions. Every time the user presses that button again, it behaves the same way (new random position and size).
My problem:
btn.setX() and btn.setY() don't seem to behave as expected. I would have thought that they would determine the absolute position of the button within the screen, but using the following sample-code for init() has a weird behavior:
btn.setX(0);
btn.setY(0);
btn.setWidth(150);
btn.setHeight(150);
The size seems to be okay, but the position seems to be relative to the middle of the screen (though it also seems to depend on the size of the button since using the code presented earlier it properly fills the whole screen). I would want such position to be relative to the top-left of the screen (excluding the top's ActionBar/TitleBar, and also excluding the bottom's NavigationBar).
When running my current code, the Button actually some times ends up being off screen. What is wrong here?
Solution
I tried your code replacing the root node of the layout by a LinearLayout and it was working properly, so this means the problem is related to the inner logic of ContraintLayout. Knowing that I tried to change the position of the button thinking about constraints instead of absolute position, particularly regarding the top and start margins of the button. Therefore the launchNewAttempt() method can be something similar to this:
private void launchNewAttempt() {
final int size = (int) (minBtnSize + (maxBtnSize - minBtnSize) * rand.nextDouble());
final int left = (int) (rand.nextFloat() * (widthPixels - size));
final int top = (int) (rand.nextFloat() * (heightPixels - size));
final ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) btn.getLayoutParams();
layoutParams.width = size;
layoutParams.height = size;
layoutParams.leftMargin = left;
layoutParams.topMargin = top;
btn.setLayoutParams(layoutParams);
}
I also kept only two contraints to place the button in the layout and removed the end and bottom ones:
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp"
android:minWidth="0dp"
android:minHeight="0dp"
android:text="Start"
android:visibility="visible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Hope this will be useful to you.
Answered By - Wang
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.