모바일 프로그래밍 공부 (6)
2025-04-14 23:40:41

안드로이드 커스텀 뷰 요소 만들기

java 코드

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

public class imgAndroiView extends View {

    public imgAndroiView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

 

 

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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAlignment="center"
    tools:context=".MainActivity">

    <com.inhatc.mobile_programming_practice.imgAndroiView
        android:id="@+id/imgAndroiView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="4dp"
        android:focusable="true"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/img_androi" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

핵심 포인트

xml 코드의 ImageView를 패키지명.클래스명 으로 설정해주면 커스텀 요소를 사용 가능하다!

 

 

예제 1) 이미지를 화면의 중앙에 오도록 설정하기

 

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.NonNull;

public class imgAndroiView extends View {

    Drawable imgAndroiView;
    int ix, iy, imgWidth, imgHeight;

    public imgAndroiView(Context context, AttributeSet attrs) {
        super(context, attrs);

        imgAndroiView = this.getResources().getDrawable(R.drawable.img_androi);
        imgWidth = imgAndroiView.getIntrinsicWidth();
        imgHeight = imgAndroiView.getIntrinsicHeight();

        ix = 0;
        iy = 0;
    }

    @Override
    public void onDraw(@NonNull Canvas canvas)
    {
        imgAndroiView.setBounds(ix, iy, ix + imgWidth, iy + imgHeight);
        imgAndroiView.draw(canvas);

        super.onDraw(canvas);
    }

    @Override
    public void onSizeChanged(int x, int y, int oldx, int oldy)
    {
        ix = (x - imgWidth) / 2;
        iy = (y - imgHeight) / 2;

        super.onSizeChanged(x, y, oldx, oldy);
    }
}

 

결과

 

핵심 포인트

뷰 요소.getIntrinsicWidth / Height  : 해당 요소의 Width값 / Height 값을 가져오는 메서드

ix = (x - imgWidth) / 2 : 뷰의 중앙에 이미지를 위치시키는 방법.

x 대신 getWidth() 메서드를 사용해도 무관하다.

 

예제 2) 방향키 입력을 통해 이미지 이동시키기

 

java 코드

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class imgAndroiView extends View {

    Drawable imgAndroiView;
    int ix, iy, imgWidth, imgHeight;

    public imgAndroiView(Context context, AttributeSet attrs) { ... }

    @Override
    public void onDraw(@NonNull Canvas canvas)
    { ... }

    @Override
    public void onSizeChanged(int x, int y, int oldx, int oldy)
    { ... }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch(keyCode)
        {
            case KeyEvent.KEYCODE_DPAD_LEFT:
                ix -= 15;
                if (ix <= 0) ix = 0;
                break;
            case KeyEvent.KEYCODE_DPAD_RIGHT:
                ix += 15;
                if (ix >= getWidth() - imgWidth) ix = getWidth() - imgWidth;
                break;
            case KeyEvent.KEYCODE_DPAD_DOWN:
                iy += 15;
                if (iy >= getHeight() - imgHeight) iy = getHeight() - imgHeight;
                break;
            case KeyEvent.KEYCODE_DPAD_UP:
                iy -= 15;
                if (iy <= 0) iy = 0;
                break;
        }

        this.invalidate();
        return super.onKeyDown(keyCode, event);
    }
}

 

핵심 포인트

뷰의 좌측 상단이 (0, 0) 이므로 좌측으로 이동하면 x를 감소, 우측으로 이동하면 x를 증가

상단으로 움직이려면 y를 감소, 하단으로 움직이려면 y를 증가시키면 된다.

 

또한 이미지의 좌표도 좌측 상단이 (0, 0) 이므로 우측 혹은 하단으로 나가지 못하게 하려면 조건에 이미지의 두께 / 너비를 더해주어야 한다.

 

예제 3 ) 클릭하면 이미지를 해당 위치로 이동시키기

 java 코드

package com.inhatc.mobile_programming_practice;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class imgAndroiView extends View { ... }

    @Override
    public void onDraw(@NonNull Canvas canvas)
    { ... }

    @Override
    public void onSizeChanged(int x, int y, int oldx, int oldy)
    { ... }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) { ... }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        ix = (int)event.getX();
        iy = (int)event.getY();
        return super.onTouchEvent(event);
    }
}

 

2025-04-09 22:57:28

Activity

  • 애플리케이션의 표현 계층
  • UI 구성요소를 스크린에 표시
  • 윈도우 어플리케이션의 Form과 같은 기능을 수행

 

예제 1) 버튼을 눌러 Activity를 전환하기

 

JAVA 소스 코드)

MainActivity.java

package com.inhatc.mobile_programming_practice;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TabHost;
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;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    Button btnCow;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        btnCow = (Button)findViewById(R.id.btnCow);
        btnCow.setOnClickListener(this);

        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;
        });
    }
    @Override
    public void onClick(View view)
    {
        if (view == btnCow)
        {
            Intent cowIntent = new Intent(MainActivity.this, CowActivity.class);
            startActivity(cowIntent);
        }
    }
}

CowActivity.java

package com.inhatc.mobile_programming_practice;

import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class DogActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_dog);
        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;
        });
    }
}

 

핵심 포인트)

시작)

Intent cowIntent = new Intent(MainActivity.this, CowActivity.class);

startActivity(cowIntent);

 

종료)

finish();

 

 

예제 2) Sound에 텍스트 입력 후 OK 버튼 클릭 시 입력한 텍스트를 toast를 이용하여 출력

MainActivity.java

package com.inhatc.mobile_programming_practice;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    Button btnCow;
    Toast objToast;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        btnCow = (Button)findViewById(R.id.btnCow);
        btnCow.setOnClickListener(this);

        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;
        });
    }
    @Override
    public void onClick(View view)
    {
        if (view == btnCow)
        {
            Intent cowIntent = new Intent(MainActivity.this, CowActivity.class);
            startActivityForResult(cowIntent, 1);
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1)
        {
             String strData = data.getStringExtra("Animal_Sound");
             objToast = Toast.makeText(this, strData, Toast.LENGTH_LONG);
             objToast.show();
        }
    }
}

CowActivity.java

package com.inhatc.mobile_programming_practice;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class CowActivity extends AppCompatActivity implements View.OnClickListener{
    Button btnOK;
    EditText editSound;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_cow);

        btnOK = (Button)findViewById(R.id.btnOK);
        btnOK.setOnClickListener(this);

        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;
        });
    }
    @Override
    public void onClick(View view)
    {
        if (view == btnOK)
        {
            Intent CallIntent = getIntent();
            editSound = (EditText)findViewById(R.id.editTextSound);
            CallIntent.putExtra("Animal_Sound", editSound.getText().toString());
            setResult(RESULT_OK, CallIntent);
            finish();
        }
    }
}

 

결과)

 

 

핵심 포인트)

시작)

startActivityForResult(cowIntent,  1);

 

@Override

protected void onAcitivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1) {

        String strData = data.getStringExtra("Animal_Sound");

        objToast = Toast.makeText(this, strData, Toast.LENGTH_LONG);

        objToast.show();

    }

}

 

종료)

CallIntent.putExtra("Animal_Sound", edtSound.getText().toString());

setResult(RESULT_OK, CallIntent);

finish();

 

 

 

 

 

 

 

 

2025-04-01 01:12:26

예제1)  버튼을 누르면 EditText의 Text가 변경되게 하기

Java 소스 코드

package com.inhatc.mobile_programming_practice;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TabHost;
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;

public class MainActivity extends AppCompatActivity {

    private Button btnCall;
    EditText ObjET;

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

        btnCall = (Button)findViewById(R.id.button);
        ObjET = (EditText)findViewById(R.id.editTextText);

        btnCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void  onClick(View view)
            {
                ObjET.setText("통화중...");
            }
        });

        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;
        });
    }

}

 

주요 표인트

버튼에 이벤트를 달아 주기

Button.setOnClickListener(View.OnClickListener()

{

    @Override

    public void onClick(View view) {

        ....

    }

});

 

 

예제 2)

 

Java 소스코드

package com.inhatc.mobile_programming_practice;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TabHost;
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;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button btnCall;
    EditText ObjET;

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

        btnCall = (Button)findViewById(R.id.button);
        ObjET = (EditText)findViewById(R.id.editTextText);
        btnCall.setOnClickListener(this);

        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;
        });
    }
    @Override
    public void onClick(View view)
    {
        String strPhoneNo = ObjET.getText().toString();
        if(view == btnCall)
        {
            if(!strPhoneNo.isEmpty())
            {
                Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel: " + ObjET.getText()));
                dialIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(dialIntent);
            }
            else{
                ObjET.setText("Input Phone Number...");
            }
        }
    }
}

결과)

 

핵심 포인트

public class MainActiviry extends AppCompatActivity  implements View.OnClickListener

부모 클래스로부터 메소드를 재정의 하기위한 implements

 

Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel: ") + EditText.getText())

uri 전환 시 콜론(:)을 넣지 않으면 양식에 맞지 않아 에러가 난다!

 

dialIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(dialIntent)

 

예제 3) 바로 전화로 연결되게 java코드 변경하기

ACTION_DIAL -> ACTION_CALL

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

    <uses-feature
        android:name="android.hardware.telephony"
        android:required="false" />
    <uses-permission android:name="android.permission.CALL_PHONE"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Mobile_Programming_Practice"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

결과)

핵심 포인트)

Intent 형 dialIntent를 DIAL_CALL로 변경

AndroidManifast.xml 에 

<uses-features

android:name="android.hardware.telephony"

android:require="false />

<uses-permission android:name="android.permission.CALL_PHONE"/>

추가 후

앱 설정에서 권한 부여

 

 

예제 4)

java 소스 코드)

package com.inhatc.mobile_programming_practice;

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TabHost;
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;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    TextView objTV;
    View objLayout;
    RadioButton rdoScreenSet;
    RadioButton rdoScreenReset;
    CheckBox chkColor_R;
    CheckBox chkColor_G;
    CheckBox chkColor_B;
    int bkColor = 0xFFFFFFFF;
    String strData;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        objTV = (TextView)findViewById(R.id.textView);
        objLayout = findViewById(R.id.main);

        rdoScreenSet = (RadioButton)findViewById(R.id.radioButton1);
        rdoScreenReset = (RadioButton)findViewById(R.id.radioButton2);
        rdoScreenSet.setOnClickListener(this);
        rdoScreenReset.setOnClickListener(this);

        chkColor_R = (CheckBox)findViewById(R.id.checkBox1);
        chkColor_G = (CheckBox)findViewById(R.id.checkBox2);
        chkColor_B = (CheckBox)findViewById(R.id.checkBox3);
        chkColor_R.setOnClickListener(this);
        chkColor_G.setOnClickListener(this);
        chkColor_B.setOnClickListener(this);

        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;
        });
    }
    @Override
    public void onClick(View view)
    {
        bkColor = 0xFF000000;
        if (rdoScreenSet.isChecked())
        {
            strData = "Color Setting Mode : " + rdoScreenSet.getText().toString();
            if (chkColor_R.isChecked()) bkColor |= 0xFFFF0000;
            if (chkColor_G.isChecked()) bkColor |= 0xFF00FF00;
            if (chkColor_B.isChecked()) bkColor |= 0xFF0000FF;
        }
        else{
            strData = "Color Setting Mode : " + rdoScreenReset.getText().toString();
            chkColor_R.setChecked(false);
            chkColor_G.setChecked(false);
            chkColor_B.setChecked(false);
            if (chkColor_R.isPressed()||chkColor_G.isPressed()||chkColor_B.isPressed())
                strData = "Setting the color setting mode to Set.";
        }
        objLayout.setBackgroundColor(bkColor);
        objTV.setTextColor(Color.GRAY);
        objTV.setText(strData);
    }

}

 

결과) 

핵심 포인트

라디오 버튼과 체크박스 모두 isChecked()로 선택 여부를 확인할 수 있다!

setChecked() 로 선택의 가능 여부 또한 정할 수 있으며,

isPressed() 로 클릭되었는지 확인할 수 있다

2025-04-01 00:27:21

예제 1) 탭 레이아웃 구성하기

 

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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TabHost
        android:id="@+id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout_editor_absoluteX="110dp"
        tools:layout_editor_absoluteY="159dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

                <LinearLayout
                    android:id="@+id/tab1"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/textView"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="This is the Artists Tab" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab2"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/textView2"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="This is the Albums Tab" />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab3"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/textView3"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="This is the Songs Tab" />
                </LinearLayout>
            </FrameLayout>
        </LinearLayout>
    </TabHost>
</androidx.constraintlayout.widget.ConstraintLayout>

Java 코드

package com.inhatc.mobile_programming_practice;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.TabHost;
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;

public class MainActivity extends AppCompatActivity {
    TabHost myTabHost = null;
    TabHost.TabSpec myTabSpec;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        myTabHost = (TabHost)findViewById(R.id.tabhost);
        myTabHost.setup();

        myTabSpec = myTabHost.newTabSpec("Artists")
                        .setIndicator("Artists")
                        .setContent(R.id.tab1);
        myTabHost.addTab(myTabSpec);

        myTabSpec = myTabHost.newTabSpec("Albums")
                        .setIndicator("Albums")
                                .setContent(R.id.tab2);
        myTabHost.addTab(myTabSpec);

        myTabSpec = myTabHost.newTabSpec("Songs")
                        .setIndicator("Songs")
                                .setContent(R.id.tab3);
        myTabHost.addTab(myTabSpec);

        myTabHost.setCurrentTab(0);

        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;
        });
    }
}

 

결과

 

 

주요 포인트

Java 를 이용한 tab 요소 추가 :

TabSpec = TabHost.newTabSpec("탭 명").setIndicator("탭 명").setContent(R.id.탭 id);

TabHost.addTab(TabSpec);

 

 

 


예제2)  탭 요소의 색 변경

 

Java 코드

package com.inhatc.mobile_programming_practice;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.TabHost;
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;

public class MainActivity extends AppCompatActivity {
    TabHost myTabHost = null;
    TabHost.TabSpec myTabSpec;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);

        myTabHost = (TabHost)findViewById(R.id.tabhost);
        myTabHost.setup();

        myTabSpec = myTabHost.newTabSpec("Artists")
                        .setIndicator("Artists")
                        .setContent(R.id.tab1);
        myTabHost.addTab(myTabSpec);

        myTabSpec = myTabHost.newTabSpec("Albums")
                        .setIndicator("Albums")
                                .setContent(R.id.tab2);
        myTabHost.addTab(myTabSpec);

        myTabSpec = myTabHost.newTabSpec("Songs")
                        .setIndicator("Songs")
                                .setContent(R.id.tab3);
        myTabHost.addTab(myTabSpec);

        myTabHost.setCurrentTab(0);

        myTabHost.getTabWidget().getChildAt(0).setBackgroundColor(Color.RED);
        myTabHost.getTabWidget().getChildAt(1).setBackgroundColor(Color.GREEN);
        myTabHost.getTabWidget().getChildAt(2).setBackgroundColor(Color.BLUE);

        for (int i = 0; i < myTabHost.getChildCount(); i++)
        {
            myTabHost.getTabWidget().getChildAt(i).getLayoutParams().height=150;
        }

        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;
        });
    }
}

 

결과

주요 포인트

Java 를 이용한 tab 요소 속성 변경

 

TabHost.getTabWidget().getChildAt(index)

 

tab배경 색 변경

TabHost.getTabWidget().getCihldAt(index).setBackgroundColor(Color.BLUE);

 

tab높이 지정

TabHost.getTabWidget().getChildAt(index).getLayoutParams().height = 150;

2025-03-24 10:47:01

안드로이드 앱 구성요소

component element functino
Activity application의 프리젠테이션 계층
UI component를 화면에 표시
Windows application의 Form과 동일 Function
Intenet Reciver 메시지 전달 Framework
Event handler Function
Sercive UI와 관계없이 오랫동안 존재하면서 실행되는 코드
background로 실행 (예 : MediaPlayer)
Content Provider Application data 공유
DB(SQLite) 연동

 

Activity

Component Element Function
OnCreate() Activity가 생성될 때 처음 호출
리소스  초기화
fincdViewById(int) 메소드 호출 : widget 검색
setContentView(int) 메소드 호출 : widget 화면 출력
Onstart() Activity 화면 출력 시 호출
OnResume() Activity stack 의 Top에 위치
Activity 화면 출력 및 입력 처리시 호출
OnPause() Activity 1 -> Activitty 2 : Activity 1의 내용 저장
데이터 저장, animation 중지, CPU 점유 작업 중단 등 수행
OnStop() 더이상 Activity가 stack의 Top에 위치하지 않으므로 Activity 출력 안됨
OnDestroy() 시스템에서 Activity 제거

 

   
Foreground activity 최상위 화면의 activity로 가장 중요한 프로세스.
메모리 부족 시 마지막으로 제거
Visible activity 화면에 보이는 activity로 foreground activity가 아닌 activity
Background activity 화면에 보이지 않고 stop 상태의 activity
메모리 부족 시 foreground, visible activity보다 먼저 제거
onSaveInstanceState(Bundle savedInstanceState) 메소드 호출 - savedInstanceState : 중요 저장 데이터 저장

Empty Process
Service, Broadcast Reciver Class와 같이 acvity, application component도 없는 프로세스
메모리 부족 시 즉시 제거

 

 


 

2025-03-17 19:20:19

프로젝트 생성

  • 애플리케이션 이름
    • Project명 ( 공백 없이 입력 )
    • 응용 프로그램 명
  • 회사 도메인
    • user.companyname.com
  • 패키지 이름
    • 2단계 이상 입력
    • com.companyname.appname
      • 폴더 생성 구조 : com\companyname\appname
  • Activity 생성
    • 클래스명 ( 공백 없이 입력 )

 

안드로이드 앱 개발 프로세스

 

 

 

안드로이드 프로젝트 구조

 

  • 안드로이드 프로젝트 파일
File Function
.gradle Build 환경 설정
.idea Copyright, Scope 등 설정
app App관련 source, resource 파일
컴파일 후 생성되는 class 파일
gradle Gradle wrapper는 적절한 Gradle binary를 자동으로 다운로드 해주는 기능
.gitignore Git 에서 Project 별 ignore할 필요가 있는 파일 및 폴더 설정
build.gradle module의 build 방법이 정의 된 script
build에 사용할 SDK 버전, 애플리케이션 버전, 라이브러리 등 설정
gradle.properties Gradle 속성 저장
gradlew Gradle wrapper를 통해 빌드를 진행하기 위한 script
gradlew.bat Gradle wrapper를 통해 빌드를 징행하기 위한 script
local.properties Android SDK 폴더 지정
settings.gradle Gradle 설정

 

  • 안드로이드 app 폴더
Folder Function
app build generated assets 외부데이터 (DB, raw data) 저장
res Resource 파일
source R file
intermediates apk *.apk 파일/ *.json 파일
assets 외부 데이터 ( DB, raw data ) 저장
dex dex file
javac Classes 파일
manifest 애플리케이션을 구성하는 기본요소인 Activity, Sercice, Content Provider, Intents, Broadcast Reciver, Notifications를 정의하고 그 메타데이터들을 제공하는 XM: 문서 파일
outputs logs log file
lib      
src main java Mainactivity.java 파일 저장
res Resource 파일 저장

 

textView의 문자열을 "Welcome to my android world!"로 변경하기

 

source code)

<?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:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Welcome to my Android World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

result )

 

 

 

Java 코드로 TextView의 속성을 변경하기

 

source code)

package com.inhatc.mobile_programming_practice;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
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;

public class MainActivity extends AppCompatActivity {

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

        TextView objTV = findViewById(R.id.textView);
        objTV.setText("Android Programming!");
        objTV.setTextColor(Color.BLUE);
        objTV.setGravity(Gravity.CENTER);
        objTV.setTextSize(32);

        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;
        });
    }
}

 

result )

 

Edit Text 속성을 사용하기

 

source code)

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

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="text"
        android:text="Google : "
        android:editable="true"
        android:layout_marginTop="146dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

OR

package com.inhatc.mobile_programming_practice;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
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;

public class MainActivity extends AppCompatActivity {

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

        TextView objET = findViewById(R.id.editText);
        objET.setText("Google : ");
        objET.setGravity(0x01);

        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;
        });
    }
}

 

result )

 

source code)

package com.inhatc.mobile_programming_practice;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
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;

public class MainActivity extends AppCompatActivity {

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

        TextView objET = findViewById(R.id.editText);
        objET.setText("Google : ");
        objET.setGravity(0x01);

        String str = objET.getText().toString();
        objET.setText(str + "Android Programming");

        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;
        });
    }
}

 

result )