[ 실행 화면 ]
|
||
이번 구현 목록은 키워드 중 자격증 키워드를 눌렀을때 나오는 xml창 구현하기!
아마 이전 포스팅까지는 자격증이 아니었던 것 같은데 쓸 내용을 생각하다보니 자격증이 생각이나서..
한개의 키워드를 자격증 키워드로 변경시켰다.
해당 xml에서 오른쪽 또는 왼쪽으로 화면을 슬라이드 했을 때 사진들이 차례로 나왔으면 좋겠다고 생각했고
인터넷 서치 결과 ViewPager을 적용하면 화면 구현이 가능하다는 걸 알게됐다.
참고 사이트는 아래 사이트이다!
https://haruple.tistory.com/163
위 사이트에서 구현하는 방법을 확인하고 xml 내용을 바꿔서 화면 구성을 해줬당 ㅎㅎ
본격적으로 코드를 작성하기 전에, ViewPager2와 CircleIndicator이 build.gradle.kts에 있는지 확인해야한다.
나의 경우 둘 다 없었어서, libs.versions.toml에 다음과 같이 추가해준 후, build.gradle.kts 파일도 수정해줬다.
[ libs.versions.toml ]
[versions]
agp = "8.6.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
appcompat = "1.7.0"
material = "1.12.0"
activity = "1.9.2"
constraintlayout = "2.1.4"
viewpager2Version = "1.1.0"
circleindicatorVersion = "2.1.6"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2Version" }
circleindicator = { group = "me.relex", name = "circleindicator", version.ref = "circleindicatorVersion" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
내가 추가해 준 부분은 [ versions ] 부분에서 viewPager2Version과 circleindicatorVersion을 추가했고
[ libraries ] 에서 viewPager2와 circleindicator도 위와 같이 추가해줬다.
이렇게 추가해 준 후 build.gradle.kts 파일로 넘어가자!
[ build.gradle.kts ]
plugins {
alias(libs.plugins.android.application)
}
android {
namespace = "com.example.introducemyself"
compileSdk = 34
defaultConfig {
applicationId = "com.example.introducemyself"
minSdk = 27
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
dependencies {
implementation(libs.appcompat)
implementation(libs.material)
implementation(libs.activity)
implementation(libs.constraintlayout)
implementation(libs.viewpager2) // ViewPager2 추가
implementation(libs.circleindicator) //circleindicator 추가
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
}
implementation (libs.viewPager2)
implementation (libs.circleindicator) 을 추가해주고 상단에 뜨는 sync now를 눌러주면 된다!
* 달라진 파일들만 업로드
1. activity_license.xml (새로 생성)
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/license_layout"
android:background="#F2EDED"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_margin="10dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="48dp">
<TextView
android:fontFamily="@font/font"
android:textSize="25sp"
android:gravity="center"
android:layout_width="0dp"
android:layout_weight="8"
android:layout_height="match_parent"
android:text="※ 자격증 목록 ※"/>
<Button
android:textStyle="bold"
android:text="←"
android:backgroundTint="#BA8E71"
android:layout_weight="2"
android:id="@+id/btn_home3"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
<FrameLayout
android:layout_gravity="center"
android:layout_width="400dp"
android:layout_height="500dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_gravity="center"
android:clipToPadding="false"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:layout_marginBottom="10dp"/>
<me.relex.circleindicator.CircleIndicator3
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginBottom="10dp"
android:layout_gravity="bottom"/>
</FrameLayout>
</LinearLayout>
</androidx.drawerlayout.widget.DrawerLayout>
여기에서 기존 xml들과 달리 ViewPager를 사용하기 위해서 추가한 부분은
<FrameLayout
android:layout_gravity="center"
android:layout_width="400dp"
android:layout_height="500dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_gravity="center"
android:clipToPadding="false"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:layout_marginBottom="10dp"/>
<me.relex.circleindicator.CircleIndicator3
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginBottom="10dp"
android:layout_gravity="bottom"/>
</FrameLayout>
이 부분이다! 참고로 ViewPager를 쓰기 위해서는 이후에 만들 frame_xml과 FrameLayout 크기가 동일해야한다.
현재 여기서는 FrameLayout을 width 400dp, height 500dp로 주었다.
CircleIndicator은 몇개의 창들 중 내가 몇번째 사진을 보고 있는지 확인해주는 느낌인데,
흰색으로 설정해놔서 내 화면에서는 잘 안보이는듯... 참고하기~
2. MainActivity.java (자격증 버튼 클릭 시 LicenseActivity.java로 넘어가기)
package com.example.introducemyself;
import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.activity.EdgeToEdge;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.drawerlayout.widget.DrawerLayout;
public class MainActivity extends AppCompatActivity {
Button btn_study;
Button btn_language;
Button btn_bowling;
TextView me_bowling;
TextView me_study;
Button btn_drawer;
TextView me_programming;
//DrawerLayout과 View 2개를 만들어준다.
private DrawerLayout drawerLayout;
private View drawerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.drawer_layout), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
drawerLayout = findViewById(R.id.drawer_layout);
drawerView = findViewById(R.id.drawer);
btn_bowling=findViewById(R.id.btn_bowling);
btn_bowling.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(MainActivity.this, BowlingActivity.class);
startActivity(intent);
}
});
btn_language=findViewById(R.id.btn_language);
btn_language.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(MainActivity.this, LanguageActivity.class);
startActivity(intent);
}
});
btn_study=findViewById(R.id.btn_study);
btn_study.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(MainActivity.this, LicenseActivity.class);
startActivity(intent);
}
});
me_bowling=findViewById(R.id.me_bowling);
me_bowling.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(MainActivity.this, LanguageActivity.class);
startActivity(intent);
}
});
me_study=findViewById(R.id.me_study);
me_study.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(MainActivity.this, LicenseActivity.class);
startActivity(intent);
}
});
me_programming=findViewById(R.id.me_programming);
me_programming.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(MainActivity.this, BowlingActivity.class);
startActivity(intent);
}
});
btn_drawer = findViewById(R.id.btn_drawer);
btn_drawer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawerLayout.openDrawer(drawerView);
}
});
drawerLayout.setDrawerListener(listener);
drawerView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
}
//drawerlayout을 왼쪽,오른쪽으로 슬라이드했을떄 이곳에서 상태값을 받아옴
//추가 기능을 해주고싶을때 여기서 만들기
DrawerLayout.DrawerListener listener = new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
//오픈이 완료됐을때
@Override
public void onDrawerOpened(@NonNull View drawerView) {
}
//슬라이드 닫혔을때
@Override
public void onDrawerClosed(@NonNull View drawerView) {
}
//상태가 change 됐을때
@Override
public void onDrawerStateChanged(int newState) {
}
};
}
여기는 특별히 달라진 부분이 없다.
3. LicenseActivity.java
package com.example.introducemyself;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import me.relex.circleindicator.CircleIndicator3;
public class LicenseActivity extends AppCompatActivity {
private ViewPager2 mPager;
private FragmentStateAdapter pagerAdapter;
private int num_page = 5;
private CircleIndicator3 mIndicator;
Button btn_home3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_license);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.license_layout), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
btn_home3=findViewById(R.id.btn_home3);
btn_home3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent 객체 생성
Intent intent = new Intent(LicenseActivity.this, MainActivity.class);
startActivity(intent);
}
});
/**
* 가로 슬라이드 뷰 Fragment
*/
//ViewPager2
mPager = findViewById(R.id.viewpager);
//Adapter
pagerAdapter = new MyAdapter(this, num_page);
mPager.setAdapter(pagerAdapter);
//Indicator
mIndicator = findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
mIndicator.createIndicators(num_page,0);
//ViewPager Setting
mPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
/**
* 이 부분 조정하여 처음 시작하는 이미지 설정.
* 2000장 생성하였으니 현재위치 1002로 설정하여
* 좌 우로 슬라이딩 할 수 있게 함. 거의 무한대로
*/
mPager.setCurrentItem(1000); //시작 지점
mPager.setOffscreenPageLimit(5); //최대 이미지 수
mPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
if (positionOffsetPixels == 0) {
mPager.setCurrentItem(position);
}
}
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
mIndicator.animatePageSelected(position%num_page);
}
});
}
}
최대 이미지 수나 시작 지점을 내가 몇개의 화면을 돌릴 것인지에 따라 수정시켜줘야한다.
4. MyAdapter.java
package com.example.introducemyself;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
public class MyAdapter extends FragmentStateAdapter {
public int mCount;
public MyAdapter(FragmentActivity fa, int count) {
super(fa);
mCount = count;
}
@NonNull
@Override
public Fragment createFragment(int position) {
int index = getRealPosition(position);
if(index==0) return new Fragment_1();
else if(index==1) return new Fragment_2();
else if(index==2) return new Fragment_3();
else if(index==3) return new Fragment_4();
else return new Fragment_5();
}
@Override
public int getItemCount() {
return 2000;
}
public int getRealPosition(int position) { return position % mCount; }
}
여기서도 몇개의 화면을 돌리느냐에 따라 if문 있는 부분을 수정해주면 된다.
5. frame_?.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:orientation="vertical"
android:layout_width="400dp"
android:layout_height="500dp">
<TextView
android:fontFamily="@font/font"
android:textSize="25sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="1. 컴퓨터활용능력 1급"/>
<ImageView
android:src="@mipmap/license1"
android:text="1"
android:scaleType="centerCrop"
android:layout_width="400dp"
android:layout_height="470dp"
android:textSize="50dp"
android:gravity="center"
android:textColor="#000000"
android:background="#FFCDD2"
/>
</LinearLayout>
</LinearLayout>
내가 여러개의 화면으로 나타낼 화면들을 각각의 frame xml로 구성해야한다.
나는 화면을 총 5개 구성할거니까 frame_1.xml 부터 frame_5.xml까지 총 5개의 xml을 만들어줬다.
여기서 크기는 위 activity_license.xml에서 쓴 FrameLayout 크기와 동일해야한다.
그래서 똑같이 width 400dp, height 500dp로 준 것을 볼 수 있다!!
6. Fragment_?.java
package com.example.introducemyself;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
public class Fragment_5 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.frame_5, container, false);
return rootView;
}
}
나의 경우 화면을 5개로 구성했기 때문에 Fragment_1.java~Fragment_5.java 까지 존재한다.
Fragment_? 부분을 화면에 맞는 숫자로 변경시키고,
각 파일마다 R.layout.frame_? 부분에서 frame_1~frame_5까지 설정해주면 된다.
그리고 java 파일이 추가되었으니까 마지막으로 수정해줄 AndroidManifest.xml
<?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-permission android:name="android.permission.INTERNET" />
<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.Introducemyself"
tools:targetApi="31">
<activity
android:name=".BowlingActivity"
android:exported="true">
</activity>
<activity
android:name=".LanguageActivity"
android:exported="true">
</activity>
<activity
android:name=".Fragment_1"
android:exported="true">
</activity>
<activity
android:name=".Fragment_2"
android:exported="true">
</activity>
<activity
android:name=".Fragment_3"
android:exported="true">
</activity>
<activity
android:name=".Fragment_4"
android:exported="true">
</activity>
<activity
android:name=".Fragment_5"
android:exported="true">
</activity>
<activity
android:name=".LicenseActivity"
android:exported="true">
</activity>
<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>
'프로젝트' 카테고리의 다른 글
[안드로이드 스튜디오 프로젝트] 자기소개앱_4 (AlertDialog 적용) (1) | 2024.09.09 |
---|---|
[안드로이드 스튜디오 프로젝트] 자기소개앱_3 (DrawerLayout 적용) (7) | 2024.09.06 |
[안드로이드 스튜디오 프로젝트] 자기소개앱_2 (ScrollView) (2) | 2024.09.05 |
[프로젝트] DB와 연동한 동아리 신청폼 만들기 (1) | 2024.09.05 |
[안드로이드 스튜디오 프로젝트] 자기소개앱.xml (1) | 2024.09.04 |