问题
I'm trying to create a simple timetable, (I'm a beginner). I have created a basic layout for the timetable with 7 days and 24 hours, and my idea was to insert buttons programmatically, overlaying the timetable for the correct time and duration by manipulating the position and width of the buttons, so that when clicked they display the task saved in the textview below as such:
I know how to create the buttons but after hours of searching for a working method to change their size and location to the desired values with no success I turn here for help.
As a test I made a new empty project with one premade constraint view in the design view and tried to place a single button within it and move it. Here is the code:
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ConstraintLayout constraintLayout01 = (ConstraintLayout)findViewById(R.id.constraintLayout01); //a constraint layout pre-made in design view
Button btn = new Button(this);
btn.setLayoutParams(new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT));
constraintLayout01.addView(btn);
int x = 100;
int y = 5;
ConstraintSet set = new ConstraintSet();
set.connect(btn.getId(), ConstraintSet.LEFT, constraintLayout01.getId(), ConstraintSet.LEFT, x);
set.connect(btn.getId(), ConstraintSet.TOP, constraintLayout01.getId(), ConstraintSet.TOP, y);
}
}
The button appears within the constraint view but no matter how I change x and y nothing ever changes location. What am I doing wrong? Also how can I change the size?
Edit1: Added a button to xml as requested:
<androidx.constraintlayout.widget.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/RootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout01"
android:layout_width="390dp"
android:layout_height="645dp"
android:layout_marginStart="28dp"
android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="@+id/button2"
android:layout_width="38dp"
android:layout_height="41dp"
android:layout_marginStart="100dp"
android:layout_marginTop="100dp"
android:text=""
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
edit2:
logcat after adding set.clone and set.applyTo:
2020-03-23 10:24:56.111 10888-10888/? E/.example.test0: Unknown bits set in runtime_flags: 0x8000
2020-03-23 10:24:56.201 10888-10888/com.example.test02 I/Perf: Connecting to perf service.
2020-03-23 10:24:56.210 10888-10918/com.example.test02 E/Perf: Fail to get file list com.example.test02
2020-03-23 10:24:56.210 10888-10918/com.example.test02 E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
2020-03-23 10:24:56.307 10888-10888/com.example.test02 W/.example.test0: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
2020-03-23 10:24:56.308 10888-10888/com.example.test02 W/.example.test0: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
2020-03-23 10:24:56.346 10888-10888/com.example.test02 D/AndroidRuntime: Shutting down VM
2020-03-23 10:24:56.347 10888-10888/com.example.test02 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.test02, PID: 10888
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test02/com.example.test02.MainActivity}: java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3271)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3410)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2017)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
Caused by: java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet
at androidx.constraintlayout.widget.ConstraintSet.clone(ConstraintSet.java:713)
at com.example.test02.MainActivity.onCreate(MainActivity.java:29)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3246)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3410)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2017)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7397)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
回答1:
These lines were missing
btn.setId(View.generateViewId());
set.clone(constraintLayout);
set.applyTo(constraintLayout);
Here is the working solution with the output.
public class Main_One extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_one);
ConstraintLayout constraintLayout = (ConstraintLayout)findViewById(R.id.connstraint_layout); //a constraint layout pre-made in design view
Button btn = new Button(this);
btn.setText("StackFlow");
btn.setLayoutParams(new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT));
btn.setId(View.generateViewId());
constraintLayout.addView(btn);
int x = 100;
int y = 505;
ConstraintSet set = new ConstraintSet();
set.clone(constraintLayout);
set.connect(btn.getId(), ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, x);
set.connect(btn.getId(), ConstraintSet.TOP, constraintLayout.getId(), ConstraintSet.TOP, y);
set.applyTo(constraintLayout);
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/connstraint_layout">
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
回答2:
Instead of using this line:
Button btn = new Button(this);
You should get your button directly from the XML. For example: if in the XML file, your button is named btn1. Then, use this:
Button btn = (Button)findViewbyId(R.id.btn1);
Then, try performing the operations. It should work.
来源:https://stackoverflow.com/questions/60782881/how-to-move-a-view-button-programmatically-in-a-constraint-layout