1. Animation

앱을 개발할 때 시각적으로 더 재밌고 예쁘게 개발하기 위해서 안드로이드는 애니메이션 기능을 제공한다.

 

여러가지 애니메이션들이 있지만 이 글에서는 object animator를 다뤄보겠습니다.

 

1) ObjectAnimator

  • 하나의 뷰에서 간단한 애니메이션을 이용하고자 하지만 반복적으로 동작하기를 바란다면, ObjectAnimator를 사용하면 된다.
  • ObjectAnimator의 특별한 기능이라고 한다면 XML을 이용하여 애니메이션을 만들 수 있는 장점이 있다.

 

shake_animations.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="150"
    android:fromDegrees="-10"
    android:pivotX="30%"
    android:pivotY="30%"
    android:repeatCount="1"
    android:repeatMode="reverse"
    android:toDegrees="10"
    />
  • 위와 같이 애니메이션 액션을 설정한다.

 

MainActivity.java

private void shakeAnimation() {
        Animation shake = AnimationUtils.loadAnimation(MainActivity.this,
                R.anim.shake_animation);

        binding.cardView.setAnimation(shake);

        shake.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                binding.questionTextview.setTextColor(Color.RED);
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                binding.questionTextview.setTextColor(Color.WHITE);

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
    }
  • shakeAnimator 메소드를 생성한다.
  • shake_animation.xml파일을 해당 파일로 shake라는 변수에 가져온다.
  • cardView위젯에 해당 애니메이션을 적용시킨다.
  • 애니메이션의 액션으로 빨간색으로 시작하여 하얀색으로 글자색이 바뀌도록 한다.
  • 반복적인 액션으로 앱화면에서는 글자색이 빨간색에서 하얀색으로 깜빡거리게 보인다.

 

'Android Study' 카테고리의 다른 글

Android Study(data binding)  (0) 2023.04.10
Android Study(Making App #Quiz)  (0) 2023.04.07
Android Study(Making App #Rain)  (0) 2023.04.05

1. Data Binding

  • DataBinding(데이터바인딩)은 간단하게 xml파일에 Data를 연결(binding)해서 사용할 수 있게 도와주며 Android JetPack 라이브러리의 하나의 기능 입니다.
  • findViewById를 사용하지 않아도 되며 보통 MVVM 패턴을 구현 할 때 "LiveData"와 함께 거의 필수적으로 사용합니다.
  • 즉, 데이터바인딩은 애플리케이션 로직과 레이아웃을 binding하는 데 필요한 코드를 최소화하여 코드가 줄어들게 됩니다.

 

1) 기본 사용방법

1-1 build.gradle(Module :app) 파일에 databinding요소를 추가한다.

android {
...
	buildFeatures {
    	  dataBinding true
    }
}

 

1-2  binding을 사용하는 xml 리소스 파일 수정

<layout> 아래에 data를 추가한다.

<layout 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">

    <data>

    </data>

</layout>

 

1-3 MainActivity.java에서 binding하기위해 수정

DataBindingUtil class 의 객체를 생성하고, 기존의 setContentView() 를 DataBindingUtil.setContentView() 로 대체한다.

private ActivityMainBinding binding;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

이후부터는 위젯을 findViewId()를 사용하지않아도 가져올 수 있습니다.

 

 

'Android Study' 카테고리의 다른 글

Android Study(애니메이션)  (0) 2023.04.10
Android Study(Making App #Quiz)  (0) 2023.04.07
Android Study(Making App #Rain)  (0) 2023.04.05

1. Quiz 앱 만들기

- 목표

 

  • 총 8개의 퀴즈를 만들어 화면에 퀴즈가 1번부터 8번까지 하나씩 보이게 합니다.
  • True, False 버튼을 만들어 사용자가 퀴즈의 답을 클릭하면 정답인지 아닌지 알려줍니다.
  • Prev, Next 버튼을 만들어 1번부터 8번까지 퀴즈를 앞뒤로 이동할수 있게 합니다.

 

완성화면)

 

 

1) TextView와 Button 만들기

 

  • 퀴즈가 들어가는 TextView와 각 Button을 디자인한 xml코드는 다음과 같다.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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">


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#2196F3"
        tools:context=".MainActivity">

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:contentDescription="@string/image_description"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.498"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_launcher_foreground" />

        <TextView
            android:id="@+id/question_text_view"
            style="@style/TextStyle"
            android:layout_width="0dp"
            android:layout_height="29dp"
            android:layout_marginTop="40dp"
            android:text="@string/placeholder"
            android:textColor="#212121"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

        <Button
            android:id="@+id/true_button"
            style="@style/ButtonStyle"
            android:text="@string/true_button_text"
            android:textColor="#000000"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/false_button"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

        <Button
            android:id="@+id/false_button"
            style="@style/ButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            android:text="@string/false_button_text"
            android:textColor="#000000"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/true_button"
            app:layout_constraintTop_toBottomOf="@+id/imageView" />

        <Button
            android:id="@+id/next_button"
            style="@style/ButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/next_button_text"
            android:textColor="#000000"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/prev_button"
            app:layout_constraintTop_toBottomOf="@+id/true_button" />

        <Button
            android:id="@+id/prev_button"
            style="@style/ButtonStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text="@string/prev_button_text"
            android:textColor="#000000"
            app:layout_constraintEnd_toStartOf="@+id/next_button"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/false_button" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

 

style.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="TextStyle">
        <item name="android:layout_marginStart">8dp</item>
        <item name="android:layout_marginEnd">8dp</item>
        <item name="android:fontFamily">@font/croissant_one</item>
        <item name="android:padding">@dimen/text_padding</item>
        <item name="android:textAlignment">textStart</item>
    </style>

    <style name="ButtonStyle" parent="TextStyle">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginTop">8dp</item>
        <item name="android:layout_marginBottom">8dp</item>
        <item name="android:backgroundTint">#D15858</item>
        <item name="android:textAlignment">center</item>
    </style>
</resources>

 

string.xml

<resources>
    <string name="app_name">True Citizen</string>
    <string name="false_button_text">false</string>
    <string name="true_button_text">True</string>
    <string name="prev_button_text">prev</string>
    <string name="next_button_text">next</string>
    <string name="placeholder">Question goes here</string>
    <string name="image_description">A droid icon image</string>

    <string name="question_declaration">The (U.S.) Declaration of Independence was Adopted in 1776.</string>
    <string name="correct_answer">That\'s correct</string>
    <string name="wrong_answer">That\'s incorrect</string>
    <string name="question_constitution">The Supreme law of the land is the Constitution.</string>
    <string name="question_amendments">The (U.S.) Constitution has 26 Amendments.</string>
    <string name="question_independence_rights">The two rights in the Declaration of Independence are:
        \n \t <b>life</b> \n  \t <b>pursuit of happiness</b>.</string>
    <string name="question_religion">Freedom of religion means:
        \n \t <b>You can practice any religion, or not practice a religion</b>.</string>
    <string name="question_government">Journalists is one branch or part of the government.</string>
    <string name="question_government_feds">Congress does not make federal laws.</string>
    <string name="question_government_senators">There are one hundred (100) U.S. Senators.</string>
</resources>

 

2) 기능 구현하기

목표에서 설명한 순서대로 다음과 같이 기능을 구현해보겠다.

 

2-1 화면에 퀴즈 출력

Question.java

public class Question {
    private int answerResId;
    private boolean answerTrue;

    public Question(int answerResId, boolean answerTrue) {
        this.answerResId = answerResId;
        this.answerTrue = answerTrue;
    }

    public int getAnswerResId() {
        return answerResId;
    }

    public void setAnswerResId(int answerResId) {
        this.answerResId = answerResId;
    }

    public boolean isAnswerTrue() {
        return answerTrue;
    }

    public void setAnswerTrue(boolean answerTrue) {
        this.answerTrue = answerTrue;
    }
}
  • Question 클래스를 새로 생성한다.
  • 생성자를 생성하여 각 퀴즈의 id값(answerResId), 퀴즈의 정답(answerTrue)변수들을 초기화한다.
  • 다른 클래스에서 변수를 수정할 수 있도록 getter/setter를 생성한다.

 

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;

    private Question[] questionBank = new Question[] {
            //create/instantiate/question object
            new Question(R.string.question_amendments, false),
            new Question(R.string.question_constitution, true),
            new Question(R.string.question_declaration, true),
            new Question(R.string.question_independence_rights, true),
            new Question(R.string.question_religion, true),
            new Question(R.string.question_government, false),
            new Question(R.string.question_government_feds, false),
            new Question(R.string.question_government_senators, true),
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
}
  • 뷰의 id값을 해당 파일로 가져오기 위해서 findViewById()가 아닌 binding을 사용한다.
  • 퀴즈들을 배열로 선언하기 위해서 배열형태의 questionBank를 생성한다.
  • string.xml에 있는 문제들의 id이름을 정답과 같이 하나씩 배열의 인스턴스로 생성한다.
  • setContentView로 화면을 디자인한 리소스 id를 해당 파일에서 사용할 수 있게 한다.
  • 그 밑줄은 binding 방식으로 리소스 id를 해당파일에서 사용할 수 있게 해준다.

 

2-2 Prev, Next 버튼 기능 구현

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    private int currentQuestionIndex = 0;

binding.nextButton.setOnClickListener(view -> {
            currentQuestionIndex = (currentQuestionIndex + 1) % questionBank.length;
            updateQuestion();

        });

        binding.prevButton.setOnClickListener(view -> {
            if (currentQuestionIndex > 0) {
                currentQuestionIndex = (currentQuestionIndex - 1) % questionBank.length;
                updateQuestion();
            }

        });
    }
    
    private void updateQuestion() {
        binding.questionTextView.setText(questionBank[currentQuestionIndex].getAnswerResId());

    }
}
  • next버튼 클릭 시 다음퀴즈를 보여주고 prev버튼 클릭 시 이전 퀴즈를 보여준다.
  • 먼저 updateQuestion 메소드를 생성한다.
  • 해당 메소드는 questionBank 배열을 이용해 퀴즈id값을 가져온다.
  • 처음 페이지에서 next 버튼을 클릭하면 (0+1)%8이 되어 나머지값인 1이 currentQuestionIndex 변수에 삽입된다. 따라서 updateQuestion 메소드로 넘어가 questionBank[1]이 되어 2번째 퀴즈를 보여주게 된다.
  • 2번째 페이지에서 prev버튼을 클릭하면 (1-1)%8이 되어 나머지값인 0이 currentQuestionIndex 변수에 삽입된다. 따라서 updateQuestion 메소드로 넘어가 questionBank[0]이 되어 1번째 퀴즈를 보여주게 된다.

 

2-3 True, False 버튼 기능 구현

MainActivity.java

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.trueButton.setOnClickListener(view -> checkAnswer(true));
        binding.falseButton.setOnClickListener(view -> checkAnswer(false));
	}

	private void checkAnswer(boolean userChoseCorrect) {
        boolean answerIsCorrect = questionBank[currentQuestionIndex].isAnswerTrue();
        int messageId;

        if (answerIsCorrect == userChoseCorrect) {
            messageId = R.string.correct_answer;
        }else {
            messageId = R.string.wrong_answer;
        }
        Snackbar.make(binding.imageView, messageId, Snackbar.LENGTH_SHORT)
                .show();

    }
  • checkAnswer 메소드를 생성해 boolean 리턴타입을 가진 userChosenCorrect변수를 선언한다.
  • answerIsCorrect 변수에 각 퀴즈에 실제 정답을 가져와 삽입한다.
  • 정답과 오답시에 출력문들의 리소스값을 messageId 변수에 삽입한다.
  • Snackbar를 이용해 정답인지 오답인지 출력한다.

 

2. 앱 실행

 

'Android Study' 카테고리의 다른 글

Android Study(애니메이션)  (0) 2023.04.10
Android Study(data binding)  (0) 2023.04.10
Android Study(Making App #Rain)  (0) 2023.04.05

1. Rain 앱 만들기

- 목표

 

  • $0이라는 텍스트뷰를 만들고 make it rain 버튼을  클릭할 때마다 100,000원씩 금액이 올라간다.
  • show info 버튼을 클릭하면 Get, Rich 문구가 알람처럼 나왔다 사라진다.
  • 금액이 1,000,000원이 되면 빨간색으로 변하고 congratulations!! You get rich!! 문구가 알람처럼 나왔다 사라진다.

 

 

초기화면)

 

1) Text view와 Button 만들기

  • 사실 디자인의 경우 안드로이드 스튜디오를 사용해 만들면 gui 방식으로 편하게 만들수 있다.
  • 앱의 디자인 코드인 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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#C0CA33"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/you_have"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/you_have"
        android:textSize="16sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.176" />

    <TextView
        android:id="@+id/moneyValue"
        android:layout_width="236dp"
        android:layout_height="45dp"
        android:gravity="center"
        android:text="@string/money_value"
        android:textSize="34sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/you_have"
        app:layout_constraintVertical_bias="0.07"
        tools:ignore="TextSizeCheck" />

    <Button
        android:id="@+id/buttonMakeItRain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/make_it_rain"
        android:onClick="showMoney"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/moneyValue"
        app:layout_constraintVertical_bias="0.121" />


    <Button
        android:id="@+id/buttonShowInfo"
        android:layout_width="137dp"
        android:layout_height="51dp"
        android:onClick="showInfo"
        android:text="@string/show_info"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonMakeItRain"
        app:layout_constraintVertical_bias="0.137" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

2) 기능 구현하기

목표에서 설명한 순서대로 다음과 같이 기능을 구현해보겠다.

 

앱의 각 버튼과 텍스트뷰의 리소스 값이다.

 

string.xml

<resources>
    <string name="app_name">MakeItRain</string>
    <string name="you_have">You Have:</string>
    <string name="money_value">$0</string>
    <string name="make_it_rain">MAKE IT RAIN</string>
    <string name="show_info">SHOW INFO</string>
    <string name="test">Hello</string>
    <string name="app_info">Get, Rich</string>
    <string name="money_info">" congratulations!! You get rich!!"</string>
</resources>

 

2-1 MAKE IT RAIN 버튼 기능 구현

MainActivity.java

package com.example.makeitrain;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.material.snackbar.Snackbar;

import java.text.NumberFormat;

public class MainActivity extends AppCompatActivity {

    private TextView moneyValue;
    private int moneyCounter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        moneyValue = findViewById(R.id.moneyValue);

    }
    
    public void showMoney(View view) {
    	NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
        
    	moneyCounter += 100000;
        moneyValue.setText(String.valueOf(numberFormat.format(moneyCounter)));
        Log.d("MainActivity", "onClick: " + moneyCounter);
  • 먼저 화면에 금액을 출력하기 위해 moneyValue를 텍스트뷰로 선언한다.
  • 그 다음 moneyCounter 변수를 생성해 금액이 올라갈때마다 해당 변수에 값을 담는다.
  • 텍스트뷰로 선언한 moneyValue를 findViewById()로 main.xml에서 설정한 id값인 moneyValue를 MainActivity.java로 가져온다.
  • showMoney 메소드를 생성한다.
  • NumberFormat 클래스를 이용해 numberFormat 객체를 생성한다.
  • 버튼을 클릭할 때마다 100,000원씩 누적되도록 한다.
  • 금액이 화면에 출력되도록 setText를 이용해 moneyValue를 문자열 형태로 변환한다.

 

if (moneyCounter == 1000000) {
            moneyValue.setTextColor(Color.RED);
            Toast.makeText(MainActivity.this, R.string.money_info, Toast.LENGTH_LONG)
                    .show();
        }
}
  • showMoney 메소드 안에 if문을 삽입하여 금액이 1,000,000원이 되면
  • setTextColor를 이용해 빨간색으로 바꾼다.
  • Toast기능도 사용하여 money_info 리소스를 만들고 리소스값으로 congratulations!! You get rich!!를 삽입하여 알람도 같이 뜨게 만든다.

 

2-2 SHOW INFO 버튼 기능 구현

 

MainActivity.java

public void showInfo(View view) {

        Snackbar.make(moneyValue, R.string.app_info, Snackbar.LENGTH_LONG)
                .setAction("More", view1 -> {
                    Log.d("Snack", "showInfo: Snackbar More");
                })
                .show();
    }
}
  • showInfo 메소드를 생성한다.
  • Snackbar를 이용해 app_info 리소스를 만들고 리소스값으로 Get, Rich를 삽입한다.
  • 스낵바 안에 More 버튼을 클릭할 시 Snackbar More 라는 문구가 안드로이드 스튜디오 로그로 나타나도록 한다.

 

2. 앱 실행

 

MAKE IT RAIN 버튼 기능 구현 모습

 

 

SHOW INFO 버튼 기능 구현 모습

 

 

스낵바에 More 버튼을 클릭한 모습

 

 

'Android Study' 카테고리의 다른 글

Android Study(애니메이션)  (0) 2023.04.10
Android Study(data binding)  (0) 2023.04.10
Android Study(Making App #Quiz)  (0) 2023.04.07

+ Recent posts