- manifest란 android 빌드 도구, 운영체제및 google play에 앱에 관한 필수 정보를 설명
application
<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.Drugstore">
- android:allowBackup="true"=>데이터 백업을 할 수 있게 허용
- android:dataExtractionRules="@xml/data_extraction_rules"
=>데이터 추출 규칙을 정의하는 XML 파일을 참조- android:fullBackupContent="@xml/backup_rules"
=>백업 규칙을 정의하는 XML 파일을 참조- android:icon="@mipmap/ic_launcher"
=>애플리케이션의 아이콘을 지정- android:label="@string/app_name"
=>애플리케이션의 어플 이름 지정- android:roundIcon="@mipmap/ic_launcher_round"
=>애플리케이션의 원형 아이콘을 지정- android:supportsRtl="true"
=>오른쪽에서 왼쪽(RTL) 레이아웃을 지원하도록 설정- android:theme="@style/Theme.Drugstore"
=>앱에 적용할 기본 테마를 지정activity(첫번째 화면 설정)
<activity android:name=".First" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
- First는 클래스를 의미하며, android:exported="true">는 다른 애플리케이션이 이 액티비티를 호출할 수 있는지 여부를 결정한다.
- true로 설정된 경우, 외부 앱이 특정 인텐트를 통해 이 액티비티를 시작할 수 있다.
=>인텐트? 이러한 어플리케이션 구성요소(컴포넌트) 간에 작업 수행을 위한 정보를 전달하는 역할을 의미- 그럼 android:exported="true"> 이걸 안쓰면 어떻게 되는가?
=>앱이 설치되지 않거나 충돌 발생activity(나머지 activity들)
<activity android:name=".MainActivity" android:exported="true" /> <!-- 다른 액티비티들 --> <activity android:name=".DetailActivity" /> <activity android:name=".DetailActivity1" /> <activity android:name=".DetailActivity2" /> <activity android:name=".DetailActivity3" /> <activity android:name=".DetailActivity4" /> <activity android:name=".DetailActivity5" /> <activity android:name=".DetailActivity6" />
- MainActivity (second_main.xml 사용)
=>.MainActivity는 이 클래스는 메인 화면 또는 앱의 주요 기능을 제공하는 액티비티로 설정- android:exported="true"
=>이 속성은 외부 애플리케이션이 이 액티비티를 호출할 수 있음을 나타내고, 외부 앱에서 이 액티비티를 실행할 수 있도록 허용- 나머지 액티티들
=> exported 속성이 없으므로, 외부에서 접근할 수 없다. 앱 내부에서 호출하도록 설계
public class First extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 각 버튼 설정 Button button1 = findViewById(R.id.button); Button button2 = findViewById(R.id.button2); Button button3 = findViewById(R.id.button3); Button button4 = findViewById(R.id.button4); Button button5 = findViewById(R.id.button5); Button button6 = findViewById(R.id.button6); // 버튼 클릭 시 MainActivity로 이동 View.OnClickListener listener = v -> { Intent intent = new Intent(First.this, Second.class); startActivity(intent); }; button1.setOnClickListener(listener); button2.setOnClickListener(listener); button3.setOnClickListener(listener); button4.setOnClickListener(listener); button5.setOnClickListener(listener); button6.setOnClickListener(listener); } }
- setContentView(R.layout.activity_main)
=>이 액티비티의 UI 레이아웃을 activity_main.xml로 설정- findViewById
=>레이아웃 파일(activity_main.xml)에 정의된 버튼 요소들을 가져옴- View.OnClickListener listener = v->{...}
=>클릭 리스너를 설정
=>v->람다 표현식으로 버튼 클릭시 수행할 작업을 정의
=>람다 표현식? (매개변수) -> { 실행할 코드 }로 익명 함수를 작성할 수 있는 방법이다.- Intent intent = new Intent(First.this, Second.class);
startActivity(intent);
=>new Intent(First.this, Second.class);는 First 액티비티에서 Second 액티비티로 이동하는 Intent를 생성
=>startActivity(intent);는 Second 액티비티를 시작- 나머지 코드
=>각 버튼들에 동일한 리스너를 설정
public class Second extends AppCompatActivity { private RecyclerView recyclerView; private ItemAdapter itemAdapter; private List<Item> itemList; private boolean isDescending = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_main); // RecyclerView 초기화 및 GridLayoutManager 설정 (6칸으로 분리) recyclerView = findViewById(R.id.recycler_view); GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 6,GridLayoutManager.HORIZONTAL,false); recyclerView.setLayoutManager(gridLayoutManager); // 아이템 데코레이션 추가 recyclerView.addItemDecoration(new ItemDecoration()); // 데이터 추가 itemList = new ArrayList<>(); for (int i = 1; i <= 6; i++) { // 예시 데이터 추가 itemList.add(new Item("제목" + i, i)); } // 어댑터 설정 itemAdapter = new ItemAdapter(itemList,this); recyclerView.setAdapter(itemAdapter); // 정렬 버튼 기능 Button sortButton = findViewById(R.id.sort_button); sortButton.setOnClickListener(v -> { if (isDescending) { Collections.sort(itemList, (a, b) -> Integer.compare(b.getLikeCount(), a.getLikeCount())); } else { Collections.sort(itemList, (a, b) -> Integer.compare(a.getLikeCount(), b.getLikeCount())); } isDescending = !isDescending; itemAdapter.notifyDataSetChanged(); }); // 뒤로가기 버튼 기능 Button backButton = findViewById(R.id.back_button); backButton.setOnClickListener(v -> finish()); } // ItemDecoration 클래스 정의 (아이템 간 간격 조정) public class ItemDecoration extends RecyclerView.ItemDecoration { private final int spacing = 4; // 간격을 줄여서 아이템이 더 꽉 차게 보이도록 조정 @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = spacing; outRect.right = spacing; outRect.top = spacing; outRect.bottom = spacing; } } // ItemClickListener 인터페이스 정의 public interface ItemClickListener { void onItemClick(int position); // 위치 정보를 인자로 받아 어떤 아이템이 클릭되었는지 알 수 있습니다. } public void onItemClick(int position) { Log.d("ItemClick", "Clicked item position: " + position); // 여기서 나중에 화면 전환 기능을 추가할 수 있습니다. } }
- recyclerView: 데이터를 표시할 RecyclerView 객체
- itemAdapter: RecyclerView의 어댑터로, 데이터를 RecyclerView에 연결
- itemList: RecyclerView에 표시할 데이터 목록을 담는 리스트
- isDescending: 데이터가 내림차순인지 여부를 확인하는 변수로, 정렬 순서를 제어
- setContentView(R.layout.second_main);는 레이아웃 파일(second_main.xml)을 이 액티비티의 UI로 설정
자세히 알아보자
recyclerView = findViewById(R.id.recycler_view); GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 6, GridLayoutManager.HORIZONTAL, false); recyclerView.setLayoutManager(gridLayoutManager); recyclerView.addItemDecoration(new ItemDecoration());
- recyclerView를 초기화하고 second_main.xml에 정의된 RecyclerView를 참조
- GridLayoutManager는 RecyclerView를 그리드 형태로 표시하는 레이아웃 매니저로, 여섯 개의 열로 나눈 수평 레이아웃을 사용
- RecyclerView의 아이템 간에 간격을 설정하기 위해 ItemDecoration을 추가
itemList = new ArrayList<>(); for (int i = 1; i <= 6; i++) { itemList.add(new Item("제목" + i, i)); }
- itemList를 초기화하고 예시 데이터를 추가
itemAdapter = new ItemAdapter(itemList, this); recyclerView.setAdapter(itemAdapter); }
- itemAdapter를 초기화하고, RecyclerView에 어댑터를 설정하여 itemList에 있는 데이터를 표시
Button sortButton = findViewById(R.id.sort_button); sortButton.setOnClickListener(v -> { if (isDescending) { Collections.sort(itemList, (a, b) -> Integer.compare(b.getLikeCount(), a.getLikeCount())); } else { Collections.sort(itemList, (a, b) -> Integer.compare(a.getLikeCount(), b.getLikeCount())); } isDescending = !isDescending; itemAdapter.notifyDataSetChanged(); });
- 정렬 버튼(sort_button)을 클릭하면, itemList의 데이터를 likeCount를 기준으로 오름차순 또는 내림차순으로 정렬
- isDescending 변수의 값을 바꿔가며, 매 클릭마다 정렬 방향을 변경
- itemAdapter.notifyDataSetChanged();를 호출하여 정렬된 데이터를 RecyclerView에 갱신
Button backButton = findViewById(R.id.back_button); backButton.setOnClickListener(v -> finish());
- 뒤로 가기 버튼(back_button)을 클릭하면, 현재 액티비티가 종료되고 이전 화면으로 전환
public class ItemDecoration extends RecyclerView.ItemDecoration { private final int spacing = 4; @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left = spacing; outRect.right = spacing; outRect.top = spacing; outRect.bottom = spacing; } }
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ViewHolder> { private final List<Item> itemList; private final Context context; public ItemAdapter(List<Item> itemList, Context context) { this.itemList = itemList; this.context = context; } }
- ItemAdapter 클래스는 RecyclerView.Adapter를 상속하며, 제네릭 타입으로 내부 ViewHolder 클래스를 지정
- itemList는 Item 객체의 리스트로, RecyclerView에 표시할 데이터
- context는 현재의 Context를 나타내며, Intent를 생성하여 다른 액티비티로 이동할 때 필요
- 생성자는 itemList와 context를 초기화
=>final을 사용함으로써 이 변수들이 어댑터의 전체 수명 동안 불변임을 보장하며, 코드의 안정성과 가독성을 높이는 데 기여
@NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false); return new ViewHolder(view); }
- onCreateViewHolder는 ViewHolder를 생성하는 메서드로, 새로운 아이템 뷰를 생성하고 이를 ViewHolder에 래핑하여 반환
- LayoutInflater는 item_list.xml 레이아웃을 인플레이트하여 각 항목의 뷰를 생성
- 이렇게 생성된 ViewHolder는 RecyclerView에 의해 관리되며, onBindViewHolder에서 데이터와 연결
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { Item item = itemList.get(position); holder.textView.setText(item.getTitle()); // 각 아이템 클릭 시 DetailActivity로 전환하고 제목을 전달 holder.itemView.setOnClickListener(v -> { Intent intent = new Intent(context, DetailActivity.class); intent.putExtra("item_title", item.getTitle()); // 아이템 제목 전달 context.startActivity(intent); }); }
- onBindViewHolder는 뷰 홀더에 데이터를 설정하는 메서드로써 position 인덱스를 사용하여 itemList에서 데이터를 가져와 뷰에 설정
- intent.putExtra("item_title", item.getTitle());를 통해 item_title이라는 키로 아이템의 제목을 DetailActivity에 전달
- context.startActivity(intent);로 DetailActivity를 시작하여 클릭한 아이템의 제목을 새 액티비티에서 사용 가능
@Override public int getItemCount() { return itemList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { TextView textView; public ViewHolder(@NonNull View itemView) { super(itemView); textView = itemView.findViewById(R.id.item_text); } }
- getItemCount는 RecyclerView에 표시할 아이템의 총 개수를 반환.
- itemList의 크기를 반환하여 아이템 개수를 알려줌
- ViewHolder 클래스는 각 RecyclerView 항목의 뷰를 담는 래퍼 클래
- textView는 item_list.xml 레이아웃 파일에 정의된 TextView를 참조하여 각 아이템의 제목을 표시하는 역할
- 생성자에서는 itemView.findViewById(R.id.item_text);를 통해 TextView를 초기화
- Second 클래스에서 RecyclerView와 ItemAdapter가 연결된 후, RecyclerView는 각 항목의 뷰가 필요할 때마다 ItemAdapter의 onCreateViewHolder와 onBindViewHolder 메서드를 호출하여 데이터를 표시
- ItemAdapter는 onCreateViewHolder에서 뷰를 생성하고, onBindViewHolder에서 데이터를 설정하여 RecyclerView에 각 아이템이 표시될 수 있도록 연결하는 역할
public class DetailActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_detail); // Intent로 전달된 아이템 제목 받기 String itemTitle = getIntent().getStringExtra("item_title"); // TextView에 제목 표시 TextView detailText = findViewById(R.id.detail_text); if (itemTitle != null) { detailText.setText(itemTitle); // 전달받은 제목 표시 } // 뒤로가기 버튼 설정 Button backButton = findViewById(R.id.bottom_button); backButton.setOnClickListener(v -> finish()); } }
- RecyclerView 항목을 클릭하면 Intent를 통해 DetailActivity가 시작
- item.getTitle()을 통해 클릭한 아이템의 제목을 Intent에 담아 전달
-String itemTitle = getIntent().getStringExtra("item_title");는 Intent로 전달된 "item_title"이라는 키를 사용하여 제목을 가져옴- itemTitle에는 ItemAdapter에서 클릭한 아이템의 제목이 담김
-TextView detailText = findViewById(R.id.detail_text);는 second_detail.xml 레이아웃에서 TextView를 가져옴- detailText.setText(itemTitle);를 통해 전달받은 itemTitle 값을 TextView에 설정하여 화면에 제목을 표시
- Button backButton = findViewById(R.id.bottom_button);는 뒤로 가기 버튼을 찾고, backButton.setOnClickListener(v -> finish());를 통해 클릭하면 현재 액티비티를 종료하고 이전 화면으로 돌아가도록 설정