반응형

Ex05RadioButton

안드로이드 네이티브 앱 개발 수업 예제#5

주요코드

RadioButton, RadioGroup, RatingBar 알아보기

  • res폴더>>layout폴더안에 있는 activity_main.xml문서를 수정하여 화면제작
  • RadioButton 3개와 Button 1개, TextView 1개를 만들어 버튼이 클릭되었을 때 선택(Selected)되어 있는 RadioButton의 텍스트를 얻어와 TextView에 표시하기
  • RadioButton을 그냥 3개만들면 Single choice가 되지 않음. 라디어버튼3개가 하나의 그룹이 되도록 3개를 감싸는 RadioGroup뷰를 사용해야만 함.
  • RadioButton의 선택(Selected)상태가 변경될 때마다 선택된 체크박스의 텍스트를 표시하기
  • RadioButton이 아니라 RadioGroup에 리스너를 설정해야함. 선택상태 변경 리스너 객체 RadioGroup.OnCheckedChangeListener 소개
  • RatingBar 위젯의 사용법은 다른 복합버튼들과 비슷함. 다만, 레이팅값의 변화 리스너객체 OnRatingBarChangeListener를 사용해야하는 것이 다름.

실행모습

 

 

실행모습 GIF

 

 

소스코드

# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <RadioGroup
        android:id="@+id/rg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rb_kor"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="KOREA"/>
        <RadioButton
            android:id="@+id/rb_chana"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="CHINA"/>
        <RadioButton
            android:id="@+id/rb_japan"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="JAPAN"/>

    </RadioGroup>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="OK"
        android:onClick="clickBtn"/>

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="result"
        android:textSize="20sp"
        android:textStyle="bold"/>

    <RatingBar
        android:id="@+id/rating"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:numStars="5"
        android:rating="3.5"
        android:stepSize="0.5"/>


</LinearLayout>

 

 

# MainActivity.java
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RatingBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView tv;
    RadioGroup rg;

    RatingBar ratingBar;

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

        tv= findViewById(R.id.tv);
        rg= findViewById(R.id.rg);

        //RadioButton의 체크상태가 변경될 때 마다 반응하기
        //라디오버튼 사용은 Single choice이므로 개별 버튼에 리스너를 적용하여 잘 사용하지 않음 [물론, 원한다면 체크박스처럼 개별 라디오버튼에 리스터를 설정해도 됨]
        //RadioButton이 아니라 RadioGroup에게 OnCheckedChangeListener를 설정해야 함.
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {

                //체크된 RadioButton 찾아오기
                RadioButton rb= findViewById(checkedId);

                //체크된 라디오버튼의 글씨를 얻어와서 텍스트뷰에 보여주기
                tv.setText( rb.getText().toString() );

            }
        });

        //RatingBar 제어하기 - 레이팅점수 변경 리스너 사용
        ratingBar= findViewById(R.id.rating);
        ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {

            //2번째 파라미터 : 사용자가 터치를 이용해서 설정된 rating 값 (소수점 존재함. float형)
            //3번째 파라미터 : 사용자가 터치를 이용해서 점수를 변경했는지 여부
            @Override
            public void onRatingChanged(RatingBar ratingBar, float rating, boolean byUser) {
                tv.setText(rating+"점");
            }
        });

    }

    public void clickBtn(View view) {
        //체크되어 있는 RadioButton 찾아오기
        int id= rg.getCheckedRadioButtonId();
        RadioButton rb= findViewById(id);

        //체크된 라디오버튼의 글씨를 얻어와서 텍스트뷰에 보여주기
        tv.setText( rb.getText().toString() );
    }

}
반응형
반응형

이번에 소개할 예제는 다른 앱에 데이터를 공유하는 기능입니다.

앱을 사용하시다 보면  share버튼 즉, 공유버튼을 보신적이 있으실겁니다.

이 앱의 특정 글씨나 이미지를 카톡이나, 이메일, 구글클라우드, 페이스북 등에 보내는 기능이지요.

 

다행이 안드로이드는 다른 앱을 아주 쉽게 실행주는 주는 매커니즘이 있지요.

바로 Intent 를 이용하는 방법입니다.

 

Intent를 통해 내 앱의 데이터를 전달해줄(공유해줄) 앱을 실행시키면서

추가데이터(EXTRA_DATA)로 공유할 데이터를 전달해주면

아주 손쉽게 글씨나 이미지를 공유할 수 있습니다.

 

예제는 아주 간단하게 구현하여 공유하는 기능에만 초점을 두고 소개하고자 합니다.

보통 공유한 데이터가 글씨이거나 이미지인 경우가 많기에

버튼을 2개만들어 각각 텍스트와 이미지를 공유하도록 만들어 보겠습니다.

(공유할 이미지를 디바이스에서 선택하도록 하는 버튼까지 필요하니 총 3개의 버튼이겠군요.)

 

먼저 activity_main.xml 을 아래처럼 만들어 화면을 구현하겠습니다.

 

# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <!-- 텍스트 데이터 공유 버튼   -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="text share"
        android:onClick="clickTextShare"/>

    
    <!-- 공유할 이미지를 선택하기 위해 사진 or 갤러리 앱을 실행하고 이미지를 선택하도록 하는 버튼   -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="select image"
        android:backgroundTint="@color/teal_700"
        android:onClick="clickSelect"/>
    <!-- 선택된 이미지를 보여줄 이미지뷰   -->
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="200dp"/>

    <!-- 위에서 선택한 이미지를 다른 앱에 공유하는 버튼   -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Image share"
        android:onClick="clickImageShare"/>


    
    <!-- [!추가!] 혹시 공유하고자 하는 앱을 사용자가 선택했을때 어떤 앱을 선택했는지 확인하고 싶을때를 위한 버튼  -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="share callback"
        android:onClick="clickShareCallback"/>

</LinearLayout>

 

 화면이 만들어 졌으니 이제 관련 코드를 작성하기 위해 MainActivity.java 파일에서

아래의 코드를 작성해 보겠습니다.

지면을 통한 설명과 코드를 오가면서 보시고 이해하기 어려우실 수 있어서 가급적 코드에 대한 설명은 각 코드의 주석을 통해 소개하고자 합니다. 주석을 유의깊게 읽어보시면서 코드를 보시면 조금 더 쉽게 이해하실 수 있으실 겁니다.

 

# MainActivity.java

 

import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;

import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.bumptech.glide.Glide;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void clickTextShare(View view) {
        //Share 기능이 가능한 앱들을 선택할 수 있도록 앱 선택 sheet 보이기

        //기본 묵시적 인텐트
        Intent intent= new Intent();
        intent.setAction(Intent.ACTION_SEND);

        //share할 데이터 글씨를 택배기사(Intent)에게 넣기 - '키'값 : Intent.EXTRA_TEXT 
        intent.putExtra(Intent.EXTRA_TEXT, "Hello. i'm share data");
        //공유할 데이터의 타입을 설정
        intent.setType("text/plain"); //기본 글씨 MIME TYPE

        //ACTION_SEND 로 인한 앱들이 모두 아래쪽에 선택되도록 나열됨. [ex. 문자, Bluetooth, GMail, 카톡 등...]
        //startActivity(intent); // 근데 그냥 실행하면 선택화면 sheet모양이 안 이쁨.

        // 그래서 조금 이쁜 앱 선택자 이용하기 : Chooser Intent
        //기존 intent를 이용하여 이쁜 선택자 만들기
        intent.putExtra(Intent.EXTRA_TITLE, "텍스트 공유");
        Intent chooserIntent= Intent.createChooser(intent, null); //두번째 파라미터 : 선택자[Chooser Sheet] 제목 글씨 [근데 안보임(저 위 intent에 Extra로 EXTRA_TITLE 넣어야 함.)- 그래서 그냥 null]
        startActivity(chooserIntent);
    }

    //공유할 파일의 Uri - 이미지 선택하여 공유하기
    Uri imgUri;

    public void clickSelect(View view) {
        Intent intent= new Intent(Intent.ACTION_PICK).setType("image/*");
        
        //api 30이상 버전부터 startActivityForResult()가  deprecated 되어서 새로 나온 [결과를 받기 위한 액티비티 실행] 클래스인 ActivityResultLauncher 를 통해 선택된 사진의 uri를 받아오기  
        resultLauncher.launch(intent);
    }

    //[결과를 받기 위한 액티비티 실행 : ActivityResultLauncher] 객체를 생성하면서 액티비티에 등록 
    ActivityResultLauncher<Intent> resultLauncher= registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
        @Override
        public void onActivityResult(ActivityResult result) {
            //실행된 사진앱 or 갤러리앱에서 사진을 올바르게 선택하고 돌아왔는가?
            if(result.getResultCode()==RESULT_OK){
                //선택된 이미지의 경로인 uri 데이터 얻어오기
                imgUri= result.getData().getData(); 
                //이미지로드 라이브러리인 Glide 를 이용하여 이미지뷰에 보이기
                Glide.with(MainActivity.this).load(imgUri).into( (ImageView)findViewById(R.id.iv) );
            }
        }
    });


    public void clickImageShare(View view) {
        //이미지 같은 바이너리 데이터 공유하기
        
        //선택된 이미지가 없으면 공유할 데이터가 없으므로.. 확인하는 코드
        if(imgUri==null) {
            Toast.makeText(this, "공유할 이미지를 먼저 선택하세요.", Toast.LENGTH_SHORT).show();
            return;
        }

        //공유가 가능한 앱들을 실행하는 Action값을 가진 묵시적 Intent객체 생성
        Intent intent= new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TITLE, "이미지 공유"); //chooser Sheet의 제목글씨
        intent.putExtra(Intent.EXTRA_TEXT, "선택된 이미지를 공유합니다."); //chooser Sheet의 텍스트글씨

        //share할 데이터인 이미지의 경로 uri를 택배기사(Intent)에게 넣기 - '키'값 : Intent.EXTRA_STREAM 
        intent.putExtra(Intent.EXTRA_STREAM, imgUri);
        intent.setType("image/*");

        startActivity(  Intent.createChooser(intent, null)  );
    }

    
    
    //[!추가!] 혹시 공유하고자 하는 앱을 사용자가 선택했을때 어떤 앱을 선택했는지 확인하고 싶을때를 위한 코드
    public void clickShareCallback(View view) {
        //공유할 앱을 선택했을때 어떤 앱을 선택했는지 확인하기... [ LOLLIPOP_MR1 api22 버전 이상에서 가능]

        Intent intent= new Intent(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT, "Nice to meet you.");
        intent.setType("text/palin");

        //선택결과를 방송을 듣는 리시버 객체 생성 - 이 .java문서와 별도로 BroadcastReceiver클래스를 상속하는 클래스를 ShareChooserBroadcastReceiver.java 문서에 작성
        Intent receiverIntent= new Intent(this, ShareChooserBroadcastReceiver.class);
        PendingIntent pendingIntent= PendingIntent.getBroadcast(this, 100, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP_MR1){
            Intent chooserIntent= Intent.createChooser(intent, null, pendingIntent.getIntentSender());
            startActivity(chooserIntent);
        }else{
            Toast.makeText(this, "앱선택 리시버 등록 못함", Toast.LENGTH_SHORT).show();
            startActivity(  Intent.createChooser(intent, null)  );
        }

    }

}

 

마지막 버튼 클릭 콜백메소드인 clickShareCallback()은 필수로 구현하는 내용이 아니라

추가적으로 소개해드린 내용이니 우선 기본 텍스트와 이미지 공유만 먼저 작성해서 테스트해보시고

추가로 사용자가 선택한 공유앱이 무엇이지 알아야만 하는 특별한 상황이 있다면 추가로 구현해 보시기 바랍니다.

 

이 예제는 단순하고 다른 앱에 데이터를 공유하는 아주 기본적인 코드만 소개한 것이니

이 코드를 기반으로 응용하여 본인이 원하는 기능을 앱에 구현해보시기 바랍니다.

 

※이 포스트는 아직 완성이 아닙니다. 실행사진과 리시버클래스파일코드 등 추가로 더 작성될 예정이니 참고바랍니다.

반응형
반응형

Ex04CompoundButton

안드로이드 네이티브 앱 개발 수업 예제#4

 

주요코드

ChecxBox, ToggleButton, Switch, RadioButton같은 CompoundButton(복합버튼) 알아보기

  • res폴더>>layout폴더안에 있는 activity_main.xml문서를 수정하여 화면제작
  • CheckBox 3개와 Button 1개, TextView 1개를 만들어 버튼이 클릭되었을 때 선택(Selected)되어 있는 CheckBox들의 텍스트를 얻어와 TextView에 표시하기
  • CheckBox 버튼의 선택(Selected)상태가 변경될 때마다 선택된 체크박스의 텍스트를 표시하기 - 선택상태 변경 리스너 객체 OnCheckedChangeListener 소개
  • ToggleButton의 선택변화리스너 OnCheckedChangeListener를 통해 On/OFF상태 반응하기
  • Switch 위젯의 사용법은 ToggleButton과 같음. 보여지는 UI모양만 다름. 요즘은 switch 뷰가 더 많이 선호됨

 

실행모습 

1. 시작 화면     2. 체크박스의 선택 후 버튼클릭한 화면     3. Toggle or Switch버튼 선택변경 화면

 

 

실행모습 GIF

 

 

소스코드

# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <CheckBox
        android:id="@+id/cb01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Apple"
        android:checked="true"/>
    <CheckBox
        android:id="@+id/cb02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Banana"/>
    <CheckBox
        android:id="@+id/cb03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Orange"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="확인"
        android:onClick="clickBtn"/>

    <ToggleButton
        android:id="@+id/toggle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textOff="꺼짐"
        android:textOn="켜짐"/>

    <Switch
        android:id="@+id/sw"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sound"/>

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="result"
        android:textSize="30sp"
        android:textStyle="bold"
        android:textColor="#000000"/>


</LinearLayout>

 

 

# MainActivity.java
package com.kitesoft.ex04compoundbutton;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.ToggleButton;

public class MainActivity extends AppCompatActivity {

    CheckBox cb01, cb02, cb03;
    TextView tv;

    ToggleButton toggleButton;
    Switch sw;

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

        cb01= findViewById(R.id.cb01);
        cb02= findViewById(R.id.cb02);
        cb03= findViewById(R.id.cb03);

        tv= findViewById(R.id.tv);

        //체크박스의 체크상태가 변경되는것을 듣는 리스너객체 생성 및 추가
        CompoundButton.OnCheckedChangeListener changeListener= new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                //체크상태가 변경될때 마다 실행되는 메소드
                String s="";

                if( cb01.isChecked() ) s += cb01.getText().toString();
                if( cb02.isChecked() ) s += cb02.getText().toString();
                if( cb03.isChecked() ) s += cb03.getText().toString();

                tv.setText( s );

            }
        };

        cb01.setOnCheckedChangeListener(changeListener);
        cb02.setOnCheckedChangeListener(changeListener);
        cb03.setOnCheckedChangeListener(changeListener);


        toggleButton= findViewById(R.id.toggle);
        toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {

                tv.setText(  isChecked+"" );

            }
        });

        sw= findViewById(R.id.sw);
        sw.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                tv.setText( isChecked+"" );
            }
        });


    }

    //onClick속성이 부여된 View가 클릭되면 자동으로
    //실행되는 콜백메소드
    public void clickBtn(View v){

        //선택되어 있는 CheckBox의 글씨 얻어오기
        String s="";

        if( cb01.isChecked() ) s += cb01.getText().toString();
        if( cb02.isChecked() ) s += cb02.getText().toString();
        if( cb03.isChecked() ) s += cb03.getText().toString();

        tv.setText( s );

    }

}

 

 


 

 

 

 

kitesoft2058/Ex04CompoundButton

안드로이드 네이티브 앱 개발 수업 예제#4. Contribute to kitesoft2058/Ex04CompoundButton development by creating an account on GitHub.

github.com

 

반응형
반응형

Ex03ImageView

안드로이드 네이티브 앱 개발 수업 예제#3

 

주요코드

Button 클릭 이벤트를 통해 ImageView 이미지 변경 및 ImageView에 클릭이벤트 적용하기

  • res폴더>>layout폴더안에 있는 activity_main.xml문서를 수정하여 화면제작
  • 각각의 버튼을 클릭하였을 때 ImageView가 보여주는 그림을 변경하기
  • ImageView에 클릭이벤트를 적용하여 ImageView를 클릭할 때 마다 이미지가 차례로 변경되도록 하기 (총 13개의 국기 이미지가 차례로 변경, 마지막 이미지 다음에는 다시 첫번째 이미지로 무한루프)

 

실행모습

1. 첫 시작 화면          2. AUSTRALIA 버튼을 클릭했을 때 모스

 

 

 

3. CANADA 버튼 클릭 화면            4. 국기 이미지 클릭 화면

 

실행모습 GIF

 

 

 

소스코드

# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <!-- 이미지를 보여주는 뷰 -->
    <!-- 이미지파일들을 res폴더>>drawable폴더안에 복사붙이기(주의! 대문자나 특수문자는 안됨. 숫자도 첫글자 안됨)-->
    <!-- src 속성 : source의 약자로서 보여줄 이미지파일의 위치를 지정 ( @/drawerble/korea ) -->
    <!-- scaleType 속성 : 이미지의 scale(확대/축소) 방법을 선택지정 [center/fitXY/centerCrop등.]-->
    <!-- clickable 속성 : 이미지뷰는 버튼이 아니므로 기본적으로는 클릭에 반응하지 못함. 이를 설정할 수 있음.[true/false]-->
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:src="@drawable/korea"
        android:scaleType="centerInside"
        android:background="@drawable/ic_launcher_background"
        android:clickable="true"
        android:layout_marginBottom="16dp"/>

    <!--버튼 4개를 추가하고 각 버튼을 클릭하였을 때 이미지뷰의 이미지를 변경하기-->
    <!--버튼 클릭을 제어하기 위해 버튼마다 고유의 id속성을 지정-->
    <Button
        android:id="@+id/btn01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="australia"/>
    <Button
        android:id="@+id/btn02"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="belgium"/>
    <Button
        android:id="@+id/btn03"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="canada"/>
    <Button
        android:id="@+id/btn04"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="korea"/>

</LinearLayout>

 

# MainActivity.java
package com.kitesoft.ex03imageview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    // xml에서 만들 뷰들을 제어하기 위한 참조변수들을 MainActivity의 멤버변수로 선언
    ImageView iv;
    Button btnAus, btnBel, btnCan, btnKor;

    // 이미지뷰를 클릭하였을 때 차례로 국기 이미지가 변경되는 코드를 연습하기 위한 int형 변수
    int num=0;

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

        // xml에서 작성한 View들 id로 찾아와서 참조하기
        iv= findViewById(R.id.iv);
        btnAus= findViewById(R.id.btn01);
        btnBel= findViewById(R.id.btn02);
        btnCan= findViewById(R.id.btn03);
        btnKor= findViewById(R.id.btn04);

        // 버튼 4개의 클릭에 반응하기 위한 리스너 설정
        // 리스너는 저 아래 onCreate()메소드 밖에 MainActivity의 멤버변수로서 생성하였음.
        // 1개의 리스너객체가 4개의 버튼 클릭에 모두 반응
        btnAus.setOnClickListener(listener);
        btnBel.setOnClickListener(listener);
        btnCan.setOnClickListener(listener);
        btnKor.setOnClickListener(listener);

        //이미지뷰를 클릭하는 것을 듣는 리스너 생성 및 추가
        iv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //이미지뷰가 보여주는 이미지를 변경하기 : 특별한 상황이 아니면 이미지의 파일명 알파벳 abc순으로 이미지가 관리되고 있어서
                //처음 이미지에 숫자 1을 더하면 다음그림을 지정할 수 있게됨. [ 정확한 내용은 R.java에 대한 이해 필요 ]
                iv.setImageResource(R.drawable.australia+num);

                //보여주는 이미지의 번호를 변경..최대 6개만 반복적으로 돌아가면서 보여주도록..
                num++;
                if(num>6){
                    num=0;
                }

            }
        });


    }//onCreate Method..

    //클릭을 듣는 리스너 객체 생성
    View.OnClickListener listener= new View.OnClickListener(){

        //콜백메소드
        @Override
        public void onClick(View view) {
            //버튼을 클릭하면 실행되는 영역

            int id= view.getId();//4개의 버튼 중 현재 클릭된 버튼뷰의 id들 얻어오기
            switch ( id ){
                case R.id.btn01:
                    //이미지뷰가 보여주는 이미지를 변경하기
                    iv.setImageResource(R.drawable.australia);
                    break;

                case R.id.btn02:
                    iv.setImageResource(R.drawable.belgium);
                    break;

                case R.id.btn03:
                    iv.setImageResource(R.drawable.canada);
                    break;

                case R.id.btn04:
                    iv.setImageResource(R.drawable.korea);
                    break;
            }

        }
    };

}

 

 


 

 

 

kitesoft2058/Ex03ImageView

안드로이드 네이티브 앱 개발 수업 예제#3. Contribute to kitesoft2058/Ex03ImageView development by creating an account on GitHub.

github.com

 

반응형
반응형

Ex02Widget

안드로이드 네이티브 앱 개발 수업 예제#2

 

주요코드

Button 클릭 이벤트를 통해 TextView의 글씨변경 및 EditText를 통한 사용자 입력

  • res폴더>>layout폴더안에 있는 activity_main.xml문서를 수정하여 화면제작
  • 버튼을 클릭하였을 때 사용자가 EditText를 통해 입력한 글씨를 얻어와서 TextView의 글씨를 변경해보기
  • 안드로이드 이벤트처리 기법을 알아보는 예제로서 리스너객체에 대한 이해 및 활용

실행모습

1. 초기화면,    2.EditText에 글씨 입력화면,      3. 버튼 클릭시에 EditText의 글씨를 TextView에서 보여주는 화면

 

 

실행모습 GIF

 

 

 

 

소스코드

 

# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <!--텍스트뷰의 글씨나 속성을 변경하는 등의 제어를 하려면 .java에서 이 텍스트뷰를 참조해야함-->
    <!--참조하려면 반드시 View들은 id속성을 가지고 있어야함.- View를 구별하는 식별자 -->
    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello"
        android:textSize="40sp"
        android:textStyle="bold"
        android:gravity="center_horizontal"/>

    <!--버튼에 text속성으로 글씨를 지정하면 자동으로 대문자로 보여짐-->
    <!--textAllCaps속성으로 대문자로 할지 여부 지정 [true/false]-->
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"
        android:textAllCaps="false"/>
    <!-- 먼저 작성하고 버튼클릭시에 텍스트뷰의 글씨 변경 연습. MainActivity.java에서 코드작성-->
    <!-- 연습 완료 후 사용자로 부터 글씨를 입력받을 수 있는 EditText 뷰를 추가-->

    <!-- 사용자로부터 글씨를 입력받을 수 있는 뷰-->
    <!-- hint : 글씨를 입력하기 전에 회색으로 보여지는 힌트글씨 지정 - 글씨를 입력하면 자동으로 안보임 -->
    <EditText
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="input text"
        android:textSize="20sp"/>

</LinearLayout>

 

# MainActivity.java
package com.kitesoft.ex02widget;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    //멤버변수
    TextView tv; //참조변수
    Button btn;
    EditText edit;

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

        //xml에서 만들어진 View객체를 id로 찾아와서 참조변수에 대입
        tv= findViewById(R.id.tv);
        btn= findViewById(R.id.btn);
        edit= findViewById(R.id.edit);

        //버튼이 클릭되는 것을 듣는 리스너객체 생성 및 추가
        btn.setOnClickListener(new View.OnClickListener() {

            //버튼을 클릭하면 자동으로 실행되는 콜백메소드
            @Override
            public void onClick(View view) {
                //EditText에 써있는 글씨를 얻어오기.
                Editable editable= edit.getText();
                String s= editable.toString();

                //얻어온 글씨를 TextView에 설정
                tv.setText(s);
            }
        });

    }

}

 


 

 

 

 

kitesoft2058/Ex02Widget

안드로이드 네이티브 앱 개발 수업 예제#2. Contribute to kitesoft2058/Ex02Widget development by creating an account on GitHub.

github.com

 

반응형
반응형

Ex01Widget

안드로이드 네이티브 앱 개발 수업 예제#1

 

주요코드

액티비티가 보여줄 화면을 구성하는 Widget(View)을 이용하여 UI화면 제작하기

  • res폴더>>layout폴더안에 있는 activity_main.xml문서를 수정하여 화면제작
  • 글씨를 보여주는 TextView를 통해 뷰의크기, 색상, 배경, 패딩, 마진, 정렬, autoLink등에 대해 알아보는 예제
  • TextView가 여러개이므로 최상위 root뷰로 LinearLayout사용(수직배치:orientation="vertical")

 

실행모습

기본 실행 화면

 

www.naver.com   링크를 클릭하였을 때 네이버웹페이지가 실행되는 모습

 

 

# activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 본인 안에 있는 Child View들을 모두 [수직/수평 - orientation속성으로 지정 ]으로 배치하는 ViewGroup 레이아웃 클래스-->
<LinearLayout 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:padding="16dp"
    android:background="#DDEEEE"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <!-- 뷰크기, 글씨, 글씨크기, 글씨색상, 배경색, 패딩, 마진-->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World"
        android:textSize="30sp"
        android:textStyle="bold|italic"
        android:textColor="#0000ff"
        android:background="#ffff00"
        android:padding="16dp"
        android:layout_marginTop="16dp"/>

    <!-- visibility속성 : [visible, invisible, gone] 아래 배경이미지지 후 작성. 차이점 확인하기 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="안녕하세요"
        android:textSize="24sp"
        android:textStyle="bold"
        android:visibility="invisible"
        android:layout_marginTop="8dp"/>

    <!-- 배경이미지 : res폴더>>drawable폴더 안에 koala.jpg파일 복사붙이기. (주의! 이미지파일이름에 대문자나 특수문자 안됨. 숫자 첫글자 안됨)-->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:text="asdfasdfa"
        android:background="@drawable/koala"/>

    <!-- 정렬 -->
    <!-- gravity : View안에 내용물(Content)의 위치 정렬-->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="gravity"
        android:gravity="right"
        android:background="#ffffff"
        android:padding="8dp"/>

    <!-- layout_gravity속성 : View자체의 위치 정렬 - 레이아웃의 종류에 따라 방법이 다소 상이 -->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Nice!!"
        android:background="#00ff00"
        android:padding="16dp"
        android:layout_gravity="center_horizontal"/>

    <!--긴글 출력 및 라인수 지정과 ...표시하기[ 3가지 중 선택 : end, start, middle]-실제로는 end만 되는 경우가 많음(디바이스마다 다름) -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="안녕하세요. 긴 글씨의 경우 한줄에 출력할 때 칸이 모자를 수 있습니다. 그럼 자동 줄바꿈이 일어납니다."
        android:maxLines="1"
        android:ellipsize="end"/>

    <!--autoLink 속성 : 잘 사용되지 않음. 웹이 아리라서 글씨의 링크를 좋은 UI/UX로 보지않음. 버튼이나 이미지를 클릭하는 방법 권장-->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:autoLink="web"
        android:text="http://www.naver.com"
        android:typeface="serif"/>
    <!--typeface는 에뮬레이터에서는 잘 안됨. 실디바이스는 되는 경우 많음-->

    <!-- xml리소스(strings.xml) 로 텍스트 설정하기 : res폴더>>values폴더>>strings.xml파일 수정-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/my_text"/>

</LinearLayout>

 

# res/values/strings.xml
<resources>
    <string name="app_name">Ex01Widget</string>

    <!--문자열 리소스 : 지금은 xml로 String객체를 생성하였다. 정도로 생각해도 됨. -->
    <string name="my_text">Hello android</string>
</resources>

 

- MainActivity.java는 변경한 것 없음.

# MainActivity.java
package com.kitesoft.ex01widget;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

 

 

사용된 이미지 리소스

 

출처. Windows 이미지


 

 

kitesoft2058/Ex01Widget

안드로이드 네이티브 앱 개발 수업 예제#1. Contribute to kitesoft2058/Ex01Widget development by creating an account on GitHub.

github.com

 

 

반응형
반응형

java언어만으로 액티비티 화면 구현하기 액티비티가 화면에 꾸미는 기법을 알아보기 위한 예제

  • 이 예제처럼 java언어만으로 화면을 꾸미면 다소 복잡함. Java언어의 AWT나 SWING을 익힌 분들은 좀 익숙할 수 있음.
  • 그래서 xml언어에 화면에 보여질 View들을 배치하고 이를 .java문서에서 제어하는 방식이 더 효과적이어서 이 기법을 기본으로하여 앱을 구현함.

실행모습

버튼 클릭 전 / 버튼 클릭 후 TextView 글씨 변경 화면

 

 

# MainActivity.java
package com.kitesoft.hellobyjava;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView tv;// TextView참조변수

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main); //화면에 보여줄 View를 설정하는 메소드 -주석처리

        //Java언어만으로 화면 꾸미기

        //액티비티에 놓여질 수 있는 것은 View클래스를 상속받은 클래스들만 가능함.

        //글씨를 보여주는 TextView 객체 생성 및 설정[ 참조변수 tv는 저 위에 MainActivity클래스의 멤버변수로 만들기 ]
        tv = new TextView(this);
        tv.setText("Hello world!!!!!");

        //버튼역할을 수행하는 객체 생성 및 설정
        Button btn = new Button(this);
        btn.setText("버튼");

        //액티비티는 한번에 하나의 View만 보여줄 수 있기에 View를 여러개 가질 수 있는 ViewGroup객체 생성
        LinearLayout layout = new LinearLayout(this);

        //위에서 만들었던 TextView와 Button을 ViewGroup에 추가
        layout.addView(tv);
        layout.addView(btn);

        //ViewGroup 1개를 추가하지만 그 안에 TextView와 Button이 배치되어 있어서 결국 2개의 뷰를 보여줄 수 있게됨.
        setContentView(layout);

        //버튼 클릭에 반응하는 리스너 객체 설정
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //버튼이 클릭되었을 때(on Click) 텍스트뷰의 글씨를 변경
                tv.setText("Nice to meet you.");
            }
        });

    }//onCreate method...

}//MainActivity class...

 


 

 

 

kitesoft2058/HelloByJava

두번째 안드로이드 네이티브 앱 개발 수업 예제 : 자바언어를 사용하여 화면제작. Contribute to kitesoft2058/HelloByJava development by creating an account on GitHub.

github.com

 

반응형
반응형

실행모습

기본 실행 모습

 

 

디바이스의 앱 런처화면(앱 목록) 아이콘 변경전 / 변경후

리소스 (앱 아이콘 이미지)

출처. Google Image Search

 

 

 

주요코드

AndroidManifest.xml문서를 수정하여 앱의 아이콘 및 라벨변경

# AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.kitesoft.hello">

    <!-- 앱의 아이콘과 라벨을 설정할 수 있음.-->
    <!-- icon속성 : res폴더>>drawable폴더 안에 icon.png파일 복사붙이기. (주의! 이미지파일이름에 대문자나 특수문자 안됨. 숫자 첫글자 안됨) : 지금은 해당 위치의 경로지정(@drawable/icon) 쯤으로 생각해도 됨-->
    <!-- label : 디바이스의 설치된 앱런처(앱 목록)화면에 보여지는 제목글씨 지정 : (회색글씨를 클릭하면 글씨가 써있는 경로 보임 : res폴더>>values폴더안에 strings.xml문서 열어보면 name="app_name"지정된 <string>의 Hello글씨가 화면에 보여지는 것임 : 이 글씨를 변경하면 앱제목이 바뀌어서 표시됨-->
    <!-- roundIcon : 디바이스(폰)들 중에 앱런처(앱 목록)화면을 만들때 모서리가 둥근 아이콘을 사용하는 경우에 보여질 아이콘 이미지 지정-->
    <!-- supportsRtl : 일본어처럼 오른쪽에서 왼쪽으로 글씨를 읽는 나라들의 UI를 지원하는지 여부 [ true/false ]-->
    <application
        android:allowBackup="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:roundIcon="@drawable/icon"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- 이 앱에서는 화면을 보여주는 MainActivity가 있다고 명시-->
        <activity android:name=".MainActivity">
            <intent-filter>
                <!-- 이 MainActivity가 처음 시작되는 Main 컴포넌트라고 명시 : 처음 만들면 자동으로 이렇게 되어 있음.-->
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

# res/values/string.xml
<resources>
    <string name="app_name">Hello</string>
</resources>

 

# activity_main.xml
<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!-- 글씨를 보여주는 뷰 -->
    <!-- text속성에 지정된 글씨가 화면에 보여짐 : 이 속성값을 변경하면 화면에 표시되는 글씨도 변경됨-->
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

 

# MainActivity.java
package com.kitesoft.hello;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

// 안드로이드는 화면에 무엇인가를 보여주려면 반드시 Activity를 상속받은 클래스가 있어야함.
public class MainActivity extends AppCompatActivity {

    //생성자처럼 이 MainActivity가 처음 객체로 생성될 때 자동으로 실행되는 콜백메소드
    //이 메소드안에서 화면에 보여질 내용물 뷰를 설정함
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //화면에 보여줄 View를 설정하는 메소드
        setContentView(R.layout.activity_main);
        // 파라미터로 전달된 R.layout.activity_main은 res폴더의 layout폴더안에 있는 activity_main.xml를 보여주겠다는 코드임
    }
}

 



 

 

 

kitesoft2058/Hello

첫번째 안드로이드 네이티브 앱 개발 수업 예제. Contribute to kitesoft2058/Hello development by creating an account on GitHub.

github.com

 

반응형
반응형

이전 포스트(Fragment 만들기Fragment 제어하기) 에서

레이아웃 xml 파일안에 프레그먼트(Fragment)를 만들어서

화면에 보여주고 제어하는 작업을 소개했습니다.


하지만 실제로 Fragment를 사용할 때는

XML에 프레그먼트를 작성하지 않고 자바코드로 추가합니다.

XML에 추가하면 고정적으로 화면에 추가되기 때문에 나중에

삭제가 되지 않습니다.


동적으로 추가/삭제 또는 다른 Fragment로 재배치 등의 작업을 수행하려면

자바코드에서 Fragment를 추가해야만 합니다.


이번 예제는

버튼 3개가 화면 상단에 있습니다.

처음에는 프레그먼트가 한개도 없는 상태입니다.


첫번째 'Analog'버튼을 누르면 AnalogClock를 보여주는 Fragment를 추가합니다.

두번째 'Digital'버튼을 누르면 DigitalClock을 보여주는 Fragment로 바뀝니다.

세번째 'Calendar'버튼을 누르면 CalendarView를 보여주는 Fragment로 바뀝니다.


   

 

실제 이런 동작의 형태를 보신적이 많이 있을 텐데요.

다른점은 버튼3개가 Tab으로 되어 있다는 거죠.

다음 포스트에서 Tab으로 Fragment를 바꾸는 예제도 할 겁니다.


이제 만들어보죠.


먼저 activity_main.xml 파일입니다.

Button 3개와 Fragment가 추가될 LinearLayout 1개로 구성되어 있습니다.

 

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    

    <LinearLayout 

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal">

        

        <Button android:id="@+id/btn01"

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="ANALOG"

            android:textSize="12sp"

            android:onClick="mOnClick"/>

        

        <Button android:id="@+id/btn02"

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="DIGITAL"

            android:textSize="12sp"

            android:onClick="mOnClick"/>

        

        <Button android:id="@+id/btn03"

            android:layout_width="0dp"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="CALENDAR"

            android:textSize="12sp"

            android:onClick="mOnClick"/>

        

    </LinearLayout>

    

    <LinearLayout android:id="@+id/container"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical"

        android:padding="8dp" >        

        

    </LinearLayout>    


</LinearLayout>


이제 각 버튼을 누를때 마다 추가될 Fragment 객체가 보여줄

View의 설계을 위해 레이아웃 xml파일 3개를 추가하겠습니다.

res폴더>layout폴더> 안에

'fragment_analog', 'fragment_digital', 'fragment_calendar' 로 3개의 xml 파일을 만듭니다.

모두 LinearLayout으로 만들었습니다.




각 layout xml 파일안에 원하는 View들을 추가하면 되겠죠.


이 예제에서는 단순하게 'AnalogClock', 'DigitalClock', 'CalendarView'

각각의 layout xml파일안에 추가하겠습니다.

 

3개의 layout xml 파일입니다. 

 fragment_analog.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    

    <AnalogClock 

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>    


</LinearLayout>

 

 fragment_digital.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    

    <DigitalClock 

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"/>    


</LinearLayout>

 

 fragment_calendar.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" 

    android:padding="16dp">

    

    <CalendarView 

        android:layout_width="match_parent"

        android:layout_height="match_parent"/>    


</LinearLayout>


이제

이 3개의 레이아웃 파일을 View로 만들어 보여줄 Fragment 자바파일을 3개 만들어보겠습니다.

자바 파일인 만큼 src폴더의 package에서 new메뉴를 실행시켜서

'AnalogFragment', 'DigitalFragment', 'CalendarFragment'

라는 이름의 새로운 class 자바 파일을 아래와 같이 생성하겠습니다.


당연히 Class를 만들때 Fragment를 상속받아 만드시면 됩니다.

android.app 패키지의 Fragment를 상속받으면 됩니다.


  




만들어진 3개의 Fragment 자바안에 Activity 자바파일처럼

lifecycle 콜백 메소드 중 보여줄 View를 만들어내는 onCreateView메소드를 오버라이드(Override)해서

위에 만든 3개의 레이아웃 xml파일을 View로 설정해 보겠습니다.


주석 빼면 코드가 몇 줄 안됩니다. 

 AnalogFragment.java

import android.app.Fragment;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;


public class AnalogFragment extends Fragment {

//Fragment의 lifecycle 메소드 중에서 Fragment가 보여줄 View를 설정하는 메소드

//MainActivity.java 에서 onCreate() 메소드 안에 setContentView()하듯이

//Fragment에서는 이 메소드에서 Fragment가 보여줄 View 객체를 생성해서 return 시켜줘야 함.

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

// TODO Auto-generated method stub

View view=null;//Fragment가 보여줄 View 객체를 참조할 참조변수

//매개변수로 전달된 LayoutInflater객체를 통해 fragment_analog.xml 레이아웃 파일을

//View 객체로 생성

view= inflater.inflate(R.layout.fragment_analog, null);

//생성된 View 객체를 리턴

return view;

}

}

 

 DigitalFragment.java

import android.app.Fragment;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;


public class DigitalFragment extends Fragment {

//Fragment의 lifecycle 메소드 중에서 Fragment가 보여줄 View를 설정하는 메소드

//MainActivity.java 에서 onCreate() 메소드 안에 setContentView()하듯이

//Fragment에서는 이 메소드에서 Fragment가 보여줄 View 객체를 생성해서 return 시켜줘야 함.

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

// TODO Auto-generated method stub

View view=null;//Fragment가 보여줄 View 객체를 참조할 참조변수

//매개변수로 전달된 LayoutInflater객체를 통해 fragment_digital.xml 레이아웃 파일을

//View 객체로 생성

view= inflater.inflate(R.layout.fragment_digital, null);

//생성된 View 객체를 리턴

return view;

}


}

 

 CalendarFragment.java

import android.app.Fragment;

import android.os.Bundle;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;


public class CalendarFragment extends Fragment {

//Fragment의 lifecycle 메소드 중에서 Fragment가 보여줄 View를 설정하는 메소드

//MainActivity.java 에서 onCreate() 메소드 안에 setContentView()하듯이

//Fragment에서는 이 메소드에서 Fragment가 보여줄 View 객체를 생성해서 return 시켜줘야 함.

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

// TODO Auto-generated method stub

View view=null;//Fragment가 보여줄 View 객체를 참조할 참조변수

//매개변수로 전달된 LayoutInflater객체를 통해 fragment_calendar.xml 레이아웃 파일을

//View 객체로 생성

view= inflater.inflate(R.layout.fragment_calendar, null);

//생성된 View 객체를 리턴

return view;

}


}


 이제

Fragment를 다 설계했으니 버튼을 누를때마다 Fragment가 추가되도록

MainActivity.java 파일을 작성해 보겠습니다.


주석을 참조하시기 바랍니다.

 

MainActivity.java

import android.app.Activity;

import android.app.Fragment;

import android.app.FragmentManager;

import android.app.FragmentTransaction;

import android.os.Bundle;

import android.view.View;


public class MainActivity extends Activity {

FragmentManager manager;  //Fragment를 관리하는 클래스의 참조변수

FragmentTransaction tran;  //실제로 Fragment를 추가/삭제/재배치 하는 클래스의 참조변수

Fragment frag1, frag2, frag3; //3개의 Fragment 참조변수


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//Fragment를 관리하는 FragmentManager 객체 덩어오기

manager= (FragmentManager)getFragmentManager();

//미리 3개의 Fragment 객체 생성

frag1= new AnalogFragment();

frag2= new DigitalFragment();

frag3= new CalendarFragment();

}

//Activity가 보여주는 activity_main.xml 파일에 태그문으로

//onClick속성이 설정된 View를 클릭했을 때 자동으로 호출되는 콜백 메소드

public void mOnClick(View v){

switch( v.getId() ){

case R.id.btn01:

//fragment_analog.xml을 보여주는 AnalogFragment 객체로 추가(add)

//Fragment 추가 작업을 수행하기 위해 먼저 FragmentManager에게 작업시작(beginTransaction) 요청

//Fragment를 자바에서 동적으로 추가/삭제/재배치 하려면 반드시 Transaction으로 실행

//FragmentTransction 클래스 객체를 생성 및 작업 시작

tran= manager.beginTransaction();

//Fragment 추가(add)

//첫번째 파라미터 : Fragment를 추가시킬 ViewGroup의 ID

  //                   (activity_main.xml안에 보면 버튼 아래에 있는 LinearLayout의 Id가 R.id.container)

//                  이 LinearLayout에 frag1(AnalogFragment) 객체 추가

//두번째 파라미터 : 추가시킬 Fragment 객체

tran.add(R.id.container, frag1); 

//Fragment 변경 작업을 완료했다는 메소드 호출

tran.commit();

break;

case R.id.btn02:

//fragment_digital.xml을 보여주는 DigitalFragment 객체로 추가(add)

//FragmentTransction 클래스 객체를 생성 및 작업 시작

tran= manager.beginTransaction();

//DigitalFragment 추가(add)

tran.add(R.id.container, frag2); 

//Fragment 변경 작업을 완료했다는 메소드 호출

tran.commit();

break;

case R.id.btn03:

//fragment_calendar.xml을 보여주는 CalendarFragment 객체로 추가(add)

//FragmentTransction 클래스 객체를 생성 및 작업 시작

tran= manager.beginTransaction();

//CalendarFragment 추가(add)

tran.add(R.id.container, frag3); 

//Fragment 변경 작업을 완료했다는 메소드 호출

tran.commit();

break;

}

}

}

 

위 코드에서 가장 눈여겨 볼 부분이 Fragment를 add 하는 부분이겠죠.

FragmentManager는 이전 포스트에서도 소개했으니 어떤 클래스인지는 알것이라고 간주하고

처음 보는 것이 FragmentTransaction 이라는 것이겠죠.


안드로이드는 Fragment를 추가/삭제/재배치 등의 작업을 수행하기 위해

FragmentTransaction을 사용합니다.


트랜잭션(Trasaction)이라는 용어를 알면 좀더 이해하기 쉬울텐데요.


짧게 설명하면

Transaction은 하나의 작업 흐름을 말합니다. 비슷하게 인지되는 프로세스(Process)가 있는데

다른 점은

트랜잭션은 프로세스와 다르게 롤백 기능이 있다는 것이죠.


이 롤백이 뭐냐?

예를 들어보겠습니다.

여러분이 인터넷 계좌이체 프로그램을 하나 만들고 있다고 생각해보죠.


A라는 계좌에서 100만원을 B계좌로 옮기는 부분을 눈여겨 보겠습니다.

다른 건 빼고

100만원을 이체하려면

A계좌의 잔액에서 100만원을 차감하도록 할 것이고

바로 이어서 B계좌의 잔액에 100만원을 증감하도록 해야겠죠.


물론 그런 식으로 코드를 작성했을 것이며 잘 된다고 가정해 보죠.

뺄셈 덧셈만 하면 되니 어려운 프로세스는 아니죠.


중요한 건 이 프로세스가 실행되는 도중 발생하는 예외상황에 대한 문제입니다.

무슨말이냐??


프로세서가 여러분이 작성한 코드를 한줄씩 읽어가며 실행하는 것을 아실테고

위 작업을 보면

프로세서가 먼저 A계좌에서 100만원을 빼는 코드를 실행하겠죠.

바로 이어서 B계좌에 100만원을 더하는 코드를 실행하려하겠죠.


바로 이때!!!

갑자기 퍽!! 에러가 나서 프로세서가 종료되었다면!!!!!!!!!


B계좌에 100만원 덧셈 작업은 실행이 안되고

A계좌만 100만원이 뺄셈된 상태겠죠...


그럼 이 100만원은????????

컴퓨터가 먹은(?) 것이죠.


이러면 안되잖아요. 그래서 이런 경우 하나의 작업( A에서 100빼고 B에 100추가 )이

종료되었다고 확인(commit)하기 전에 어떤 문제로 종료되면

처음 상태로 자동으로 되돌아 가도록 하는 기술이 있습니다.

이를 롤백이라고 합니다.


아주 기가막힌 기법이죠. 반드시 필요하기도 하고요.

이 롤백기능을 가진 것이 트랜잭션(Transaction) 입니다.


그래서 작업을 시작한다고 알리기 위해 begineTransaction을 실행하고 

원하는 작업을 수행한 후

마지막에 commit하면 적용되는 문법을 사용합니다.


안드로이드의 Fragment 추가/삭제/재배치는 이런 트랜잭션으로 수행하도록 설계되었습니다.

코드를 보시면 어렵지 않게 이해할 수 있을 것이라 기대합니다.


자 이제 완성했으니 실행해 볼까요?


실행결과는 아래와 같습니다.

각 버튼을 하나씩 눌러서 Fragment를 추가하는 겁니다.


  

 


버튼을 누를때 마다 Fragment가 추가(add)되는 것을 볼수 있습니다.


어! 근데 이건 제가 원하는 결과가 아니죠.

전 add가 아니라 버튼을 누를때마다 다른 Fragment를 보고 싶은 것이죠.

이럴 땐 새로운 Fragment를 추가(add)할 때 

기존 Fragment를 제거(remove)하고 추가 작업을 해야겠죠.

위 코드에서 추가 할때 tran.add() 메소드를 했듯이

제거할때는 tran.remove()메소드를 호출하면 됩니다.


생각해 보면 이 작업은 결국 재배치(replace)라는 용어로 부를 수도 있겠군요.

그래 FragmentTransaction 재배치(replace) 메소드도 가지고 있습니다.

재배치(replace)는 만약 기존에 Fragment가 없다면 자동으로 추가합니다.

편하네요.


위의 add() 코드를 replace() 코드로 변경하겠습니다.

주석은 빼고

변경된 부분은 굵은 글씨로 표시했습니다.

MainActivity.java

import android.app.Activity;

import android.app.Fragment;

import android.app.FragmentManager;

import android.app.FragmentTransaction;

import android.os.Bundle;

import android.view.View;


public class MainActivity extends Activity {

FragmentManager manager;  //Fragment를 관리하는 클래스의 참조변수

FragmentTransaction tran;  //실제로 Fragment를 추가/삭제/재배치 하는 클래스의 참조변수

Fragment frag1, frag2, frag3; //3개의 Fragment 참조변수


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//Fragment를 관리하는 FragmentManager 객체 덩어오기

manager= (FragmentManager)getFragmentManager();

//미리 3개의 Fragment 객체 생성

frag1= new AnalogFragment();

frag2= new DigitalFragment();

frag3= new CalendarFragment();

}

//Activity가 보여주는 activity_main.xml 파일에 태그문으로

//onClick속성이 설정된 View를 클릭했을 때 자동으로 호출되는 콜백 메소드

public void mOnClick(View v){

switch( v.getId() ){

case R.id.btn01:

//fragment_analog.xml을 보여주는 AnalogFragment 객체로 재배치(replace)

tran= manager.beginTransaction();

tran.replace(R.id.container, frag1); 

tran.commit();

break;

case R.id.btn02:

//fragment_digital.xml을 보여주는 DigitalFragment 객체로 재배치(replace)

tran= manager.beginTransaction();

tran.replace(R.id.container, frag2); 

tran.commit();

break;

case R.id.btn03:

//fragment_calendar.xml을 보여주는 CalendarFragment 객체로 재배치(replace)

tran= manager.beginTransaction();

tran.replace(R.id.container, frag3); 

tran.commit();

break;

}

}

}

 

동작 결과는 아래와 같습니다.

   

처음 소개했듯이 Fragment가 바뀌는 것을 확인할 수 있습니다.

마지막 CalendarView가 제대로 보이지 않으시면 CalendarView의 높이(layout_height)값을 '300dp'정도로 줄이세요.



참고로

Fragment는 Activity처럼 백스택(back stack)를 가지고 있지 않아서

현재 Fragment를 종료한다고 이전 Fragment가 보이지 않습니다.


하지만 그렇게 하고 싶을 수도 있겠죠.

만약 이전에 보여줬던 Fragment가 보이게 하려면 backstack에 Fragment를 추가해야 합니다.

코드만 한줄 더 쓰면 됩니다.

 tran= manager.beginTransaction();

 tran.replace(R.id.container, frag1);

 tran.addToBackStack(null); // 백스택에 지금 재배치한 Fragment를 추가

 tran.commit();

이렇게 하고 앱의 '뒤로가기' 버튼을 누르면

이전에 보여줬던 Fragment가 보이게 될 겁니다.



여기까지만 하고

다음 포스트에서는 이 예제를 기반으로 해서

Button이 아니라 Tab으로 Fragment가 변경되게 해보겠습니다.


반응형
반응형

이전 포스트(Fragment 만들기) 에서

레이아웃 xml 파일안에 프레그먼트(Fragment)를 만들어서

화면에 보여주는 작업을 소개했습니다.


이번에는

이렇게 만들어진 Fragment를 보여주는 Activity에서 Fragment 안에 있는 View들을 제어하는 예제입니다.


간단하게 소개하기 위해

activity_main안에 Button을 하나 만들고

이 버튼을 누르면 Fragment안에 있는 TextView의 글씨가 변경되는 예제입니다.


동작결과입니다. 간단합니다.

노란색 배경이 Fragment가 보여주는 View의 영역입니다.

MainActivity의 버튼을 눌렀더니 Fragment 안에 있는 TextView의 글씨가 Hello 변경되었습니다.


  



이전 예제를 그대로 활용하겠습니다.


먼저 activity_main.xml에 버튼하나를 추가했습니다.

굵은 글씨가 추가된 부분입니다.

 

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical">

    

    <TextView android:id="@+id/text"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="The TextView into the MainActivity"/>

    

    <Button android:id="@+id/btn"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="Change Text in the Fragment"

        android:onClick="mOnClick"/>

    

    <!-- TestFragment를 MainActivity가 보여줄 View로 고정시켜서 배치 -->

    <!-- 직접적으로 XML 레이아웃 파일에 태그문으로 생성된 Fragment는  동적으로 재배치/삭제 불가-->

    <fragment android:name="com.kitesoft.fragment.TestFragment"

        android:id="@+id/frag"

        android:layout_width="match_parent"

        android:layout_height="match_parent"/>    


</LinearLayout>

 

 


이제 제어하기 위한 자바 소스파일입니다.

가장 중요한 부분은 <fragment/>로 만들어진 Fragment

자바에서 참조하는 작업입니다.


xml에 만들어진 TextView나 ImageView 같은 View들

Java 소스코드 에서 참조하려면

findViewById()로 찾아옵니다.

메소드의 이름만 봐도 View객체를 찾으라는 것을 알수 있는 매우 직관적인 메소드명입니다.


우리가 하고자 하는 것은 Fragment를 찾는 것입니다.

Fragment는 View가 아닙니다.

이전에 사용했던 findViewById()는 좀 이상하지 않나요?

findFragmentById()가 맞지 않겠어요?

 맞습니다. 이 메소드를 사용해야 합니다. 하지만 애석하게도

Activity 클래스는 이런 메소드가 없습니다.


그래서 Activity 클래스 대신

Fragment를 제어하기 위한 별도의 클래스가 존재하게 됩니다.

Fragment를 add/remove/replace 하는 등의 작업들을 수행할 수 있도록 관리해주는

클래스라고 보면 됩니다.


이름도 참 직관적인 FragmentManager 입니다.

요놈이 findFragmentById() 메소드를 가지고 있습니다.

이 클래스 객체를 이용해서 Fragment가 보여주는 레이아웃(fragment_text.xml)안에 있는

View들을 제어합니다.


자바 소스파일입니다.

주석의 설명을 참고하시기 바랍니다.

 

 MainActivity.java

import android.app.Activity;

import android.app.FragmentManager;

import android.os.Bundle;

import android.view.View;

import android.widget.TextView;


public class MainActivity extends Activity {

TestFragment frag; //TestFragment 참조변수

FragmentManager manager; //FragmentManager 참조변수


@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//Fragment는 View가 아닌만큼 다른 Widget을 찾을 때 처럼 

//findViewById()메소드를 사용할 수 없음

//대신 findFragmentById()메소드를 사용해서 찾아와야 하지만

//Activity 클래스는 이런 메소드가 없음.

//대신 Fragment를 추가/삭제/재배치 등 제어를 할 수 있는 FragmentManager 클래스가 존재함.

//Fragment를 제어하기 위한 매니져 객체

manager= getFragmentManager();

//매니져 객체에게 findFragmentById()를 요청하면서 id 전달

frag= (TestFragment)manager.findFragmentById(R.id.frag);

}

//Activity가 보여주는 activity_main.xml 파일에 태그문으로

//onClick속성이 설정된 View를 클릭했을 때 자동으로 호출되는 콜백 메소드

public void mOnClick(View v){

switch( v.getId() ){

case R.id.btn:

//TestFragment 객체가 보여주고 있는 View 객체( fragment_test.xml 로 만들어진 View) 안에 있는

//TextView 객체를 찾아오기

TextView text= (TextView)frag.getView().findViewById(R.id.text_fragment);

//Fragment가 보여 주는 레이아웃 안에 있는 TextView의 글씨를 변경

text.setText("Hello");

break;

}

}

}


여기까지 입니다.


참고로

위의 방법은 Activity에서 Fragment안에 있는 TextView를 직접 참조해와서

제어하는 방식입니다.



객체 지향적 프로그래밍 방식의 기본 개념은


"니껀 니가!!"


즉, 그 객체의 멤버 변수는 그 객체 스스로 제어하는 것이 좋다는 것이죠.

그래야 재사용성이 높아지고

클래스 간의 독립성을 유지 할 수 있기 때문이죠.

시간이 나면 강좌게시판을 통해 자세히 설명할 예정입니다.


그래서 이를 좀 더 반영하여

Activity에서 Fragment의 TextView를 직접 제어하지 않고

Fragment의 특정 메소드에 값을 전달하고 Fragment가 전달 된 값으로 TextView의 글씨를 변경하도록 해보겠습니다.


TestFragment.java 파일과 MainActivity.java 파일의 일부분만 추가 변경해 주면 됩니다.


변경된 부분만 굵은 글씨로 소개합니다.

 

 TestFragment.java

public class TestFragment extends Fragment {

TextView text;  //TextView 참조변수

public TestFragment() {

// TODO Auto-generated constructor stub

}

//Fragment의 lifecycle 메소드 중에서 Fragment가 보여줄 View를 설정하는 메소드

//MainActivity.java 에서 onCreate() 메소드 안에 setContentView()하듯이

//Fragment에서는 이 메소드에서 Fragment가 보여줄 View 객체를 생성해서 return 시켜줘야 함.

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

// TODO Auto-generated method stub

View view=null;//Fragment가 보여줄 View 객체를 참조할 참조변수

//매개변수로 전달된 LayoutInflater객체를 통해 fragment_test.xml 레이아웃 파일을

//View 객체로 생성

view= inflater.inflate(R.layout.fragment_test, null);

//위에 만들어진 view객체 안에 있는 TextView를 찾아오기

    text= (TextView)view.findViewById(R.id.text_fragment);

//생성된 View 객체를 리턴

return view;

}

//TextView의 글씨를 변경하기 위해 만든 메소드

public void setTextViewValue(String str){

text.setText(str); //전달 받은 문자열로 TextView의 글씨를 변경

}

}

 

 



 

MainActivity.java


      //... 위 생략


      //Activity가 보여주는 activity_main.xml 파일에 태그문으로

      //onClick속성이 설정된 View를 클릭했을 때 자동으로 호출되는 콜백 메소드

public void mOnClick(View v){

switch( v.getId() ){

case R.id.btn:

   /* 이 영역은 모두 주석 처리///////////////

//TestFragment 객체가 보여주고 있는 View 객체( fragment_test.xml 로 만들어진 View) 안에 있는

//TextView 객체를 찾아오기

TextView text= (TextView)frag.getView().findViewById(R.id.text_fragment);

//Fragment가 보여 주는 레이아웃 안에 있는 TextView의 글씨를 변경

text.setText("Hello");

*/

   //Fragment 객체안에 정의 된 TextView의 글씨를 변경하는 메소드를 호출면서 "Hello"문자열 전달.

frag.setTextViewValue("Hello");

   break;

}

}


동작의 결과는 같습니다.

필자의 경우는 이 방법을 더 선호합니다.



이번에 소개된 예제는 XML안에 Fragment를 태그문을 이용해 고정적으로 만들어낸 방식입니다.

이 방식은 Fragment의 값은 바꿀 수 있어도 Fragment 자체를 동적으로 재배치 하거나 삭제 하지 못하는 단점이 있습니다.


다음 포스트에서는 동적으로 Fragment를 추가하는 예제를 소개하겠습니다.


반응형

+ Recent posts