Created
March 26, 2026 17:12
-
-
Save guiathayde/ecbdea76cd2ee453d7f2b7b7dce31a60 to your computer and use it in GitHub Desktop.
Basket Score
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?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" | |
| xmlns:tools="http://schemas.android.com/tools" | |
| android:id="@+id/main" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| tools:context=".MainActivity"> | |
| <TextView | |
| android:id="@+id/tv_score" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="32dp" | |
| android:textSize="48sp" | |
| android:textStyle="bold" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" | |
| tools:text="0 - 0" /> | |
| <TextView | |
| android:id="@+id/tv_team1" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="32dp" | |
| android:text="@string/team_1" | |
| android:textSize="24sp" | |
| app:layout_constraintEnd_toStartOf="@+id/guideline_center" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@+id/tv_score" /> | |
| <TextView | |
| android:id="@+id/tv_team2" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginTop="32dp" | |
| android:text="@string/team_2" | |
| android:textSize="24sp" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="@+id/guideline_center" | |
| app:layout_constraintTop_toBottomOf="@+id/tv_score" /> | |
| <androidx.constraintlayout.widget.Guideline | |
| android:id="@+id/guideline_center" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:orientation="vertical" | |
| app:layout_constraintGuide_percent="0.5" /> | |
| <!-- Team 1 Buttons --> | |
| <Button | |
| android:id="@+id/btn_t1_free_throw" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="16dp" | |
| android:layout_marginTop="16dp" | |
| android:text="@string/free_throw" | |
| app:layout_constraintEnd_toStartOf="@+id/guideline_center" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@+id/tv_team1" /> | |
| <Button | |
| android:id="@+id/btn_t1_two_points" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="16dp" | |
| android:layout_marginTop="16dp" | |
| android:text="@string/two_points" | |
| app:layout_constraintEnd_toStartOf="@+id/guideline_center" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@+id/btn_t1_free_throw" /> | |
| <Button | |
| android:id="@+id/btn_t1_three_points" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="16dp" | |
| android:layout_marginTop="16dp" | |
| android:text="@string/three_points" | |
| app:layout_constraintEnd_toStartOf="@+id/guideline_center" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toBottomOf="@+id/btn_t1_two_points" /> | |
| <!-- Team 2 Buttons --> | |
| <Button | |
| android:id="@+id/btn_t2_free_throw" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="16dp" | |
| android:layout_marginTop="16dp" | |
| android:text="@string/free_throw" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="@+id/guideline_center" | |
| app:layout_constraintTop_toBottomOf="@+id/tv_team2" /> | |
| <Button | |
| android:id="@+id/btn_t2_two_points" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="16dp" | |
| android:layout_marginTop="16dp" | |
| android:text="@string/two_points" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="@+id/guideline_center" | |
| app:layout_constraintTop_toBottomOf="@+id/btn_t2_free_throw" /> | |
| <Button | |
| android:id="@+id/btn_t2_three_points" | |
| android:layout_width="0dp" | |
| android:layout_height="wrap_content" | |
| android:layout_marginHorizontal="16dp" | |
| android:layout_marginTop="16dp" | |
| android:text="@string/three_points" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="@+id/guideline_center" | |
| app:layout_constraintTop_toBottomOf="@+id/btn_t2_two_points" /> | |
| <!-- Undo Button --> | |
| <Button | |
| android:id="@+id/btn_undo" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginBottom="32dp" | |
| android:layout_marginEnd="8dp" | |
| android:text="@string/undo" | |
| android:enabled="false" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toStartOf="@+id/guideline_center" /> | |
| <!-- Reset Button --> | |
| <Button | |
| android:id="@+id/btn_reset" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:layout_marginBottom="32dp" | |
| android:layout_marginStart="8dp" | |
| android:text="@string/reset_score" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintStart_toEndOf="@+id/guideline_center" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.guiathayde.basketscore; | |
| import android.os.Bundle; | |
| import android.widget.Button; | |
| import android.widget.TextView; | |
| import androidx.activity.EdgeToEdge; | |
| import androidx.appcompat.app.AppCompatActivity; | |
| import androidx.core.graphics.Insets; | |
| import androidx.core.view.ViewCompat; | |
| import androidx.core.view.WindowInsetsCompat; | |
| import androidx.lifecycle.ViewModelProvider; | |
| public class MainActivity extends AppCompatActivity { | |
| private ScoreViewModel viewModel; | |
| private TextView tvScore; | |
| private Button btnUndo; | |
| @Override | |
| protected void onCreate(Bundle savedInstanceState) { | |
| super.onCreate(savedInstanceState); | |
| EdgeToEdge.enable(this); | |
| setContentView(R.layout.activity_main); | |
| ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { | |
| Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); | |
| v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); | |
| return insets; | |
| }); | |
| viewModel = new ViewModelProvider(this).get(ScoreViewModel.class); | |
| tvScore = findViewById(R.id.tv_score); | |
| btnUndo = findViewById(R.id.btn_undo); | |
| Button btnReset = findViewById(R.id.btn_reset); | |
| Button btnT1FreeThrow = findViewById(R.id.btn_t1_free_throw); | |
| Button btnT1TwoPoints = findViewById(R.id.btn_t1_two_points); | |
| Button btnT1ThreePoints = findViewById(R.id.btn_t1_three_points); | |
| Button btnT2FreeThrow = findViewById(R.id.btn_t2_free_throw); | |
| Button btnT2TwoPoints = findViewById(R.id.btn_t2_two_points); | |
| Button btnT2ThreePoints = findViewById(R.id.btn_t2_three_points); | |
| // Team 1 actions | |
| btnT1FreeThrow.setOnClickListener(v -> viewModel.addPoints(1, 1)); | |
| btnT1TwoPoints.setOnClickListener(v -> viewModel.addPoints(1, 2)); | |
| btnT1ThreePoints.setOnClickListener(v -> viewModel.addPoints(1, 3)); | |
| // Team 2 actions | |
| btnT2FreeThrow.setOnClickListener(v -> viewModel.addPoints(2, 1)); | |
| btnT2TwoPoints.setOnClickListener(v -> viewModel.addPoints(2, 2)); | |
| btnT2ThreePoints.setOnClickListener(v -> viewModel.addPoints(2, 3)); | |
| // Undo action | |
| btnUndo.setOnClickListener(v -> viewModel.undoLastAction()); | |
| // Reset action | |
| btnReset.setOnClickListener(v -> viewModel.resetScore()); | |
| // Observe ViewModel | |
| viewModel.getTeam1Score().observe(this, score -> updateScoreView()); | |
| viewModel.getTeam2Score().observe(this, score -> updateScoreView()); | |
| viewModel.getCanUndo().observe(this, canUndo -> btnUndo.setEnabled(canUndo)); | |
| } | |
| private void updateScoreView() { | |
| int score1 = viewModel.getTeam1Score().getValue() != null ? viewModel.getTeam1Score().getValue() : 0; | |
| int score2 = viewModel.getTeam2Score().getValue() != null ? viewModel.getTeam2Score().getValue() : 0; | |
| String scoreText = getString(R.string.score_format, score1, score2); | |
| tvScore.setText(scoreText); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.guiathayde.basketscore; | |
| import androidx.lifecycle.LiveData; | |
| import androidx.lifecycle.MutableLiveData; | |
| import androidx.lifecycle.ViewModel; | |
| public class ScoreViewModel extends ViewModel { | |
| private final MutableLiveData<Integer> team1Score = new MutableLiveData<>(0); | |
| private final MutableLiveData<Integer> team2Score = new MutableLiveData<>(0); | |
| private final MutableLiveData<Boolean> canUndo = new MutableLiveData<>(false); | |
| // Store the last action to be able to undo | |
| private int lastTeam = 0; // 1 for team 1, 2 for team 2, 0 for none | |
| private int lastPoints = 0; | |
| public LiveData<Integer> getTeam1Score() { | |
| return team1Score; | |
| } | |
| public LiveData<Integer> getTeam2Score() { | |
| return team2Score; | |
| } | |
| public LiveData<Boolean> getCanUndo() { | |
| return canUndo; | |
| } | |
| public void addPoints(int team, int points) { | |
| if (team == 1) { | |
| Integer currentScore = team1Score.getValue(); | |
| team1Score.setValue((currentScore != null ? currentScore : 0) + points); | |
| } else if (team == 2) { | |
| Integer currentScore = team2Score.getValue(); | |
| team2Score.setValue((currentScore != null ? currentScore : 0) + points); | |
| } | |
| lastTeam = team; | |
| lastPoints = points; | |
| canUndo.setValue(true); | |
| } | |
| public void undoLastAction() { | |
| if (Boolean.TRUE.equals(canUndo.getValue())) { | |
| if (lastTeam == 1) { | |
| Integer currentScore = team1Score.getValue(); | |
| team1Score.setValue((currentScore != null ? currentScore : 0) - lastPoints); | |
| } else if (lastTeam == 2) { | |
| Integer currentScore = team2Score.getValue(); | |
| team2Score.setValue((currentScore != null ? currentScore : 0) - lastPoints); | |
| } | |
| lastTeam = 0; | |
| lastPoints = 0; | |
| canUndo.setValue(false); | |
| } | |
| } | |
| public void resetScore() { | |
| team1Score.setValue(0); | |
| team2Score.setValue(0); | |
| lastTeam = 0; | |
| lastPoints = 0; | |
| canUndo.setValue(false); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment