[Android Studio 사전 어플 만들기/landscape/가로화면/fragment]
오늘은 fragment를 이용해 간단한 사전 어플을 만들고, 가로 화면(폰을 가로로 눕혔을때)에 보이는 activity도 따로 만들어 볼 것이다.
가로 화면 activity는 두 개의 fragment(단어, 정의)를 한 번에 볼 수 있도록 만들었다.
word와 definition 모두 Data라는 class에 String[]으로 저장해놓은 것을 불러와 알맞게 화면에 나타낸 것이다.
그러므로 진짜 세상 모든 단어가 다 있고, 그에 따른 정의를 얻으려면 이 글이 아닌 네이버 사전 api를 연동하는 글을 찾아봐야 할 것이다.
일단, 코드부터 살펴보자!
여러 클래스와 xml이 있는데, 일단 xml부터 살펴보자.
[activity_main.xml] //세로 화면에서 fragment들을 붙일 Layout 생성
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment_container"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
[fragment_definition.xml] //definition을 보여줄 fragment
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="#FFEB3B"
tools:context=".DefinitionFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="@+id/definition"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFEB3B" />
</FrameLayout>
[fragment_word.xml] //word를 보여줄 fragment
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".WordFragment">
<!-- TODO: Update blank fragment layout -->
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/word_list"
/>
</FrameLayout>
[activity_main.xml] //가로 화면에서 fragment들을 붙인 Layout 생성
<?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:orientation="horizontal" >
<fragment
android:id="@+id/words_fragment"
android:name="com.example.dictionary.WordFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<fragment
android:id="@+id/definition_fragment"
android:name="com.example.dictionary.DefinitionFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
* 가로 화면을 위한 activity_main.xml을 만드는 방법은
[Android Tip] 화면 방향 전환 처리
Orientation(방향) 별 xml 만들기안드로이드는 기기의 세로/가로 방향이 전환되면 현재의 Activity를 삭...
blog.naver.com
이 곳에 layout_land 폴더 생성 후 만드는 방식이 정리되어 있으니 한 번 보시길 추천드림.
[WordFragment.java] //word fragment 생성
package com.example.dictionary;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class WordFragment extends Fragment {
public WordFragment() {
// Required empty public constructor
}
public interface onWordSelectedListener{
public void onWordSelected(int position);
}
onWordSelectedListener os;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_word, container, false);
ListView listview = view.findViewById(R.id.word_list);
listview.setAdapter(new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, Data.words));
os = (MainActivity)getActivity();
listview.setOnItemClickListener(new AdapterView.OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
os.onWordSelected(position);
}
});
return view;
}
}
[DefinitionFragment.java] //definition fragment 생성
package com.example.dictionary;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class DefinitionFragment extends Fragment {
public DefinitionFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_definition, container, false);
}
@Override
public void onStart() {
super.onStart();
Bundle args = getArguments();
if (args != null) {
int pos = args.getInt("position");
updateDefinitionView(pos);
}
}
public void updateDefinitionView(int position) {
//선택된 word에 따른 position에 따라 알맞은 definition으로 UI 업데이트
TextView def = (TextView) getView().findViewById(R.id.definition);
def.setText(Data.definitions[position]);
}
}
[MainActivity.java] //알맞은 definition fragment와 word fragment를 main activity에 붙임
package com.example.dictionary;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
public class MainActivity extends AppCompatActivity implements WordFragment.onWordSelectedListener{
boolean landScape = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_container) != null) {
//fragment 객체 생성 및 main activity에 wordfragment 붙이기.
WordFragment wordsfragment = new WordFragment();
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().add(R.id.fragment_container, wordsfragment).commit();
}
}
public void onWordSelected(int position) { //positon은 선택된 word의 위치
if (findViewById(R.id.fragment_container) != null) {
DefinitionFragment definitionFragment = new DefinitionFragment();
Bundle arg = new Bundle();
arg.putInt("position",position);
definitionFragment.setArguments(arg);
FragmentTransaction trans = getSupportFragmentManager().beginTransaction();
//선택된 word에 따른 알맞은 definition fragment를 activity main에 붙이기.
trans.replace(R.id.fragment_container,definitionFragment);
trans.addToBackStack(null);
trans.commit();
}
else { //가로화면인 경우, main activity에 fragment_container 없음
FragmentManager fm = getSupportFragmentManager();
DefinitionFragment newFragment =(DefinitionFragment)fm.findFragmentById(R.id.definition_fragment);
if(newFragment != null) newFragment.updateDefinitionView(position);
}
}
}
[Data.java] //dictionary 내용, 마음대로 변경하셔서 쓰시길. 단, position은 맞춰야함.
package com.example.dictionary;
public class Data {
static String[] words = {
"Fragment",
"Activity",
"ListView",
"Adapter",
"View",
"TextView",
"ListAdapter",
"ImageView",
"LayoutInflater",
"MenuInflater",
"Window",
"Log",
"Property",
"ArraySet",
"TimeUtils"
};
static String[] definitions = {
"프래그먼트(fragment)는 하니콤 버전(API 버전 11)부터 추가된 기능이다. 프래그먼트는 태블릿과 같은 넓은 화면을 가지는 모바일 장치를 위한 매카니즘이다.",
"액티비티(activity)는 사용자 인터페이스 화면을 가지는 하나의 작업을 담당하는 컴포넌트이다.",
"ListView는 스크롤 가능한 항목의 목록을 표시하는 뷰 그룹입니다.",
"Adapter 객체는 AdapterView해당 뷰에 대한 기본 데이터와 해당 뷰 간의 연결 역할을합니다. 어댑터는 데이터 항목에 대한 액세스를 제공합니다.",
"이 클래스는 사용자 인터페이스 구성 요소의 기본 구성 요소를 나타냅니다. 뷰는 화면의 직사각형 영역을 차지하며 그리기 및 이벤트 처리를 담당합니다.",
"사용자에게 텍스트를 표시하는 사용자 인터페이스 요소이다.",
"확장 Adapter은 a ListView 와 목록을 백업하는 데이터 사이의 다리 입니다. 종종 데이터는 커서에서 가져 오지만 필수는 아닙니다. ListView는 ListAdapter에 래핑 된 모든 데이터를 표시 할 수 있습니다.",
"이미지 리소스를 표시 Bitmap 또는 Drawable자원. ImageView도 일반적으로 사용 apply tints to an image되며 처리 image scaling됩니다.",
"레이아웃 XML 파일을 해당 View 객체로 인스턴스화합니다. 직접적으로 사용되지 않습니다. 대신에 getLayoutInflater () 또는 getSystemService (Class)를 사용하여 이미 현재 컨텍스트에 연결되어 있다",
"이 클래스는 메뉴 XML 파일을 Menu 객체로 인스턴스화하는 데 사용됩니다.",
"톱 레벨의 윈도우의 외관과 동작 정책의 추상 기본 클래스입니다. 이 클래스의 인스턴스는 창 관리자에 추가 된 최상위보기로 사용해야합니다. 배경, 제목 영역, 기본 키 처리 등과 같은 표준 UI 정책을 제공합니다.",
"로그 출력을 보내기위한 API. 일반적으로 로그를 작성하려면 Log.v (), Log.d (), Log.i (), Log.w () 및 Log.e () 메서드를 사용해야합니다. 그런 다음 logcat에서 로그를 볼 수 있습니다.",
"속성은 호스트 개체에 보관되는 변경 가능한 값을 나타내는 데 사용할 수있는 추상화입니다. 속성의 set (Object, Object) 또는 get (Object) 메서드는 호스트 객체의 비공개 필드 또는 \"setter\"및 \"getter\"메서드를 통해 구현하거나 다른 메커니즘을 통해 구현할 수 있습니다.",
"ArraySet은 전통적인 HashSet보다 메모리 효율이 높도록 설계된 일반적인 세트 데이터 구조입니다. 이 디자인은 ArrayMap과 매우 유사하며 모든 문제점이 설명되어 있습니다. 그러나이 구현은 ArrayMap과 별개이므로 Object 배열에는 매핑의 쌍 대신에 집합의 각 항목에 대해 하나의 항목 만 포함됩니다.",
"표준 시간대와 관련된 유틸리티 메서드가 포함 된 클래스입니다."
};
}