Error : Duplicate resource

에러가 뜨면서 빌드가 안된다.

 

원인 : res폴더에 이름은 같으나 확장자가 다를 경우

ex) testImage.png   OR   testImage.jpg

-> 이름이 같아 내부 자원에서 동일한 ID를 부여받게 된다.

((Activity명) Context).호출할 Activity 메서드()


((MainActivity) mContext).getCountSum();

이렇게 쓸 수 있는 이유는 Activity가 context를 상속하고 있기 때문입니다.


에러가 나는 경우가 있는데, 

대표적으로

Activity has been destroyed, IllegalState Exception이 뜰 때....

 

위 사진처럼 만들어 보겠습니다.

 

1. 먼저 manifest에서 theme를 NoActionBar로 바꿔줍니다.

2. 필요한 메뉴를 정의합니다. 예제를 위해 한 것과 다르게,

  • orderInCategory
  • app:showAsAction ( always, withText 등) 의 옵션이 있습니다.
  • res폴더에 menu폴더를 만들어서 작성하시면 됩니다.

3. xml에서 toolbar를 추가하도록 합니다.

4. toolbar를 부착 시키고, 옵션을 추가하고, 메소드를 Override하여 사용하면 끝입니다.

  • setSupportActionBar
  • getSupportActionBar()
    • .setTitle 제목
    • .setTitleTextColor 제목 컬러
    • .setHomeAsUpIndicator 뒤로가기 버튼을 자신이 원하는 아이콘으로 하고 싶을 경우
    • .setDisplayHomeAsUpEnabled 뒤로가기 버튼
  • OnCreateOptionMenu
  • onOptionItemSelected

 

 

사진과 같이 안드로이드에서 Tab기능을 만들어 보도록 하겠습니다.

 

1. 외부라이브러리인 design을 추가해주어야 합니다.

  • 환경설정(?)의 dependency에 들어가서 직접 추가해주셔도 되고,
  • build.gradle에 직접 implementation해주어도 됩니다. 

2. 화면 처럼 나오게 하기 위해선 Actionbar를 없애주어야 합니다. style로 가셔서 NoActionBar로 바꿔주세요

3. 탭을 구성할 layout을 변경합니다.

총 5개의 단계로 구성되어 있습니다.

3-1  Design이라는 외부 라이브러리를 성공적으로 sync하셨다면, Coord를 치시면 1번쨰의 레이아웃을 자동으로 생성해주게 됩니다. Tab이라고 하는 액션바를 추가해주게 되면 원래 있던 View와 겹치게 보이는 현상이 나타나는데 그것을 Coord Layout이 잡아주게 됩니다. 즉, 서로의 위치를 잘 postioning하게 해줍니다.

3-2 그 안에 액션바를 추가해주게 됩니다. AppBarLayout을 사용합니다. 추가하기 위해 android:theme이라는 속성을 추가해줍니다.

3-3 Toolbar는 액션바 안에서 타이틀의 메뉴 아이콘이 보일 영역을 말하며 탭 버튼이 그 아래에 보일 수 있도록 합니다.

3-4 TabLayout아웃을 추가합니다. tabMode는 고정시키는 역할, tabGravity는 탭의 아이템이 2개이든 3개든 가로방향으로 꽉 채워주도록 합니다. tabSelectedTextColor는 선택될 떄 강조할 color를 정해줍니다.

3-5 AppBar는 상단 영역, 주로 사용자가 작업을 할 공간을 그 밑에 정해줍니다. 이때, app:layout_behavior라는 속성을 꼭 넣어줘야 안드로이드가 액션바와 사용자의 영역, 즉 FrameLayout의 영역의 위치를 구분해서 나눠주게 됩니다.

 

4. 프래그먼트는 테스트를 위해 3개를 만들어줍니다. ( 과정 생략 )

5. MainActivity 전체 코드.

public class  MainActivity extends AppCompatActivity {

    Fragment1 fragment1;
    Fragment2 fragment2;
    Fragment3 fragment3;

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

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3();

        getSupportFragmentManager().beginTransaction().add(R.id.container, fragment1).commit();

        TabLayout tabs = findViewById(R.id.tabs);
        tabs.addTab(tabs.newTab().setText("친구"));
        tabs.addTab(tabs.newTab().setText("1:1채팅"));
        tabs.addTab(tabs.newTab().setText("기타"));

        tabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                int position = tab.getPosition();

                Fragment selected = null;
                if (position == 0) {
                    selected = fragment1;
                } else if (position == 1) {
                    selected = fragment2;
                } else if (position == 2) {
                    selected = fragment3;
                }

                getSupportFragmentManager().beginTransaction().replace(R.id.container, selected).commit();
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });
    }

}

5-1 먼저 우리가 만들어준 Toolbar를 등록을 해줍니다.

5-2 다음으로 Tab의 id를 얻어온 뒤, addTab을 이용해 Tab에 item을 추가해주게 됩니다.

5-3 setOnTabSelectedListener를 사용하여 tab을 클릭했을 때, 우리가 만든 각각의 프래그먼트가 보이도록 합니다.

액티비티에서 액티비티에서 또는 프래그먼트로, 여러 경로로의 데이터 전달 시에 안드로이드에서는 주로

Intent라는 객체를 이용하게 됩니다.

이 객체에 할 일을 담을 수도 있고, 어떠한 데이터를 담아서 다른 액티비티에게 전달해 줄 수 있죠.

그런데 Intent에 객체나 클래스, 자주 사용하는 ArrayList와 같은 것을 담기엔 무리가 있어 보이네요.

 

그래서 사용하는게 Parcelable이라는 객체입니다.

이 객체에는 객체를 담을 수 있습니다.

예를 들어, 어떤 데이터를 주고 받을 때, 여러분들은 데이터만을 담은 클래스를 자주 활용할 것입니다. 대표적으로 ListView를 활용할 때죠.


parcel을 이용한 데이터 클래스 만들기

먼저 여러분이 활용할 데이터 클래스를 만들어 보겠습니다.

먼저 우리는 parcel을 이용할 것이니 implements부터 해줍니다. 그러면 자동으로

1. describeContents() 와 writeToParcel을 Override시켜 줄 것입니다. 근데 비어있네요? 이것도 별도의 control이 필요하지 않은 이상 일단 그대로 둡니다.

describeContents() - Parcel 하려는 오브젝트의 종류를 정의한다. 

writeToParcel(Parcel dest, int flags) - 실제 오브젝트 serialization/flattening을 하는 메소드. 오브젝트의 각 엘리먼트를 각각 parcel해줘야 한다.

2. 다음으로는 여러분의 데이터를 만들면 됩니다. 제가 만든 예제에서는 간단하게 학생이름과 학번을 사용했습니다.

3. 이렇게 생성자를 만들고 나면, 사실 이 전에 class name에 빨간 밑줄이 그어져 있는 것을 확인 할 수 있는데, 이 부분에 마우스를 가져다놓으면 add하라는 명령어 하나가 보일 것입니다. 그걸 그대로 클릭해주면! 위의 형식이 완성됩니다.

Parcel에서 데이터를 un-marshal/de-serialize하는 단계를 추가해줘야 한다. 그러기 위해서 Parcelable.Creator 타입의 CREATOR라는 변수를 정의해야 한다. 이 변수를 정의하지 않으면 안드로이드는 다음과 같은 익셉션을 발생한다.

Parcelable protocol requires a Parcelable.Creator object called CREATOR

4. 물론, 비어있던 writeToParcel도 채워진게 보이죠? 

5. 자, 그러면 이제 클래스 데이터를 옮길 준비가 되었습니다.

 

순서대로 하면 parcel에 data를 쓰고, 즉 flatten해주고 이것들을 담은 parcel을 가져와 생성자를 이용해 객체를 만들어주게 됩니다.


데이터 옮겨서 확인하기

자 그럼 이제 데이터가 잘 옮겨지는지 확인 해봅시다.

예제는 상당히 간단하니, 코드만 보여드리고 MainActivity의 레이아웃에는 버튼 하나만 추가된 상태입니다!(쉽게 따라할 수 있게 하기 위해서)

이제 putParcelableArrayListExtra를 사용할 수 있습니다.

putExtra에도 배열을 보낼 수 있습니다. (putExtra의 한계는 어디까지인지? 확인안해봄.여기서 중요한건 아니니)

설명이 따로 필요가 없습니다. 바로 결과를 확인해보죠

결과 액티비티는 이렇게 만들었구요. 레이아웃을 사용하지 않기 위해서 로그창으로 띄웠습니다.

추가로 객체만 보냈을 때의 주석을 보시면, 저런 식으로 받을 수 있습니다. 참고!

 

결과

 

 

Reference

http://aroundck.tistory.com/57

'# 기타 공부한 것들 > Android' 카테고리의 다른 글

안드로이드 toolbar 만들기  (0) 2018.08.16
안드로이드 Tab 만들기  (0) 2018.08.15
Volley 사용하기(GET, POST)  (0) 2018.08.06
Nevigation View 만들기  (0) 2018.07.26
Toobar, appbar 경계선 없애기  (0) 2018.07.25