마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

tag값과 Intent를 통해서 텍스트뷰와 이미지뷰 전달하기

0 추천

현재 안드로이드 스튜디오를 통해서 개발공부를 진행중인 학생입니다.

step by step 안드로이드 프로그래밍 책을 보며 공부중인데 main_activity에서 두개의 레이아웃을 item1, item2으로 id를 설정해주고 tag값을 지정해서 picture_activity에다가 tag값을 Intent로 불러서 여기다가 디스플레이하는 걸 하려고 했는데 안됩니다..

정확히 말하자면 item1은 이미지도 잘 출력이 되고 텍스트도 잘 출력이 되는데 item2는 클릭했을 때 에뮬레이터 속 어플이 강제종료가 됩니다. 아시는 분들 있으시다면 가르쳐주시면 감사하겠습니다!!!

혼자서 오류를 해결해보려고 노력해봤지만 도저히 안되어서 왔습니다. 바로 코드를 보도록 하겠습니다.

 

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void displayPicture(View view) {
        int id = view.getId();
        LinearLayout layout = findViewById(id);
        String tag = (String) layout.getTag();
        Toast.makeText(this, "클릭한 아이템 : " + tag, Toast.LENGTH_SHORT).show();
        Intent it = new Intent(this, Picture.class);
        it.putExtra("it_tag", (String) tag);
        startActivity(it);
    }
}

 

Picture.java

import androidx.appcompat.app.AppCompatActivity;
public class Picture extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.picture);
        TextView tv_title = findViewById(R.id.title);
        TextView tv_author = findViewById(R.id.artist);
        ImageView iv_picture = findViewById(R.id.picture);
        Intent it = getIntent();
        String tag = it.getStringExtra("it_tag");
        Resources res = getResources();
        int id_title = res.getIdentifier("title" + tag, "string", getPackageName());
        String title = res.getString(id_title);
        tv_title.setText(title);
        int id_author = res.getIdentifier("artist" + tag, "string", getPackageName());
        String author = res.getString(id_author);
        tv_author.setText(author);
        int id_picture = res.getIdentifier("picture" + tag, "string", getPackageName());
        String picture = res.getString(id_picture);
        int id_img = res.getIdentifier(picture, "drawable", getPackageName());
        Drawable drawable = res.getDrawable(id_img);
        iv_picture.setBackground(drawable);
    }
    public void closePicture() {
        finish();
    }
}

 

logcat 오류

Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0
        at com.example.gallery.Picture.onCreate(Picture.java:41)

Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0
        at com.example.gallery.Picture.onCreate(Picture.java:42)

Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
        at com.example.gallery.MainActivity.displayPicture(MainActivity.java:22)

 

이미지뷰를 가져올 때 오류가 발생하는거 같은데 tag1의 텍스트뷰와 이미지뷰는 잘 가져와서 잘 보여주는데 tag2는 이미지뷰를 가져오는 과정에서 오류가 발생하는것 같습니다. 이미지뷰를 디스플레이하는 코드를 주석으로 바꾸고 실행해보면 텍스트뷰는 잘 가져오고 잘 보여줍니다.

kcoder (330 포인트) 님이 2021년 10월 17일 질문

2개의 답변

+1 추천
 
채택된 답변

에러메세지로 봤을 때, layout.getTag()에 int 또는 integer값이 들어가 있는 것으로 보이구요. view.getTag()를 하면 Object를 리턴합니다. 따라서 안전하게 처리하려면 getTag의 테이터 타입을 검사해 볼 수 있습니다. 그리고 먼저 원래 타입인 int로 변환한 다음, String으로 다시 변환해야 할 것 같습니다. 100% Integer값이 확실하다면 타입 캐스팅을 할 수도 있구요. 

public void displayPicture(View view) {
        Object tagValue = view.tagTag();
        if (!(tagValue instanceof Integer)) {
              throw new IllegalArgumentException("파라미터로 전달 된 뷰의 tag 속성에는 Integer 타입만 허용됩니다.]");
        }

        int tagInt = (int) tagValue;
        String tag = "" + tagInt;
        // 나머지 생략
}

 

그리고 디버거를 사용하는 방법은 아래 Google IO의 동영상을 참고해 보세요. 디버깅시 expression에 있는 값을 확인하는 방법도 나옵니다. 제가 길게 쓰는 것 보다는 이 비디오를 보시는게 더 빠를 것 같아요.

https://www.youtube.com/watch?v=rjlhSDhFwzM

 

그리고, 지금 보고 따라하시는 예제는 그렇게 실용적인 예제는 아니지만, tag값을 가지고 처리하기 보다는 그냥 array resource를 만들고  array resource 만 넘기면 훨씬 간단할 것으로 보입니다.

array.xml
<resources>
    <string-array name="artwork1">
        <item>Starry Night</item>
        <item>고흐</item>
        <item>starry_night</item>
    </string-array>

     <string-array name="artwork2">
        <item>Still Lief with kettle</item>
        <item>세잔느</item>
        <item>still_life_with_kettle</item>
    </string-array>
</resources>


layout.tag에 array name만 넘겨서

int stringArrayid = ....
String[] artworkInfo = getStringArray(stringArrayid);
String title = artworkInfo[0];
String artist = artworkInfo[1];
String drawableName = artworkInfo[2];

아니면, 좀 더 정확한 방법으로는 원하는 시는 그림에 대한 데이터를 만들어서 이걸 화면에 보여준 다음, 화면도 이 데이터를 기초로 가져오게 하는 것이 훨씬 좋은 접근 방법입니다.

public class Artwork {
    // 필드를 읽기 전용으로 만듦
    private final int id;
    private final String title;
    @DrawableRes private final int drawableId;

    // 생성자, Getter & Setter 생략
}

private final List<Artwork> artworks = Arrays.asList(
    new Artwork(1, getString(R.string.title1), R.drawable.starry_night),
    new Artwork(2, getString(R.string.title2), R.drawable.still_life_with_kettle)
);

//위의 데이터를 기반으로 RecyclerView를 사용해서 화면에 데이터를 보여주시거나(권장), 맵핑해주시면 됩니다.

//데이터 맵핑의 경우, layout의 tag에 resource ID 대신에 artwork id를 저장.
int selectedArtworkId = (int) layout.getTag();
Artwork selectedArtwork = null;
for (Artwork artwork in artworks) {
     if (selectedArtworkId == artwork.id) {
           selectedArtwork = artwork;
           break;
     }
}

if (selectedArtwork == null) {
    throw new IllegalArgumentException("전달된 ID를 가진 artwork를 찾을 수 없습니다.");
}

displayArtwork(selectedArtwork);

 

spark (226,420 포인트) 님이 2021년 10월 18일 답변
kcoder님이 2021년 10월 18일 채택됨
답변 감사합니다 열심히 공부하겠습니다!
+1 추천
리소스 파일에는 님의 코드에서 사용하는 string과 drawable이 다 등록되어 있나요?

String resource에 아래에 해당하는 ID들이 잘 등록되어 있는지 체크해 보세요.

"title" + tag

"artist" + tag

"picture" + tag
spark (226,420 포인트) 님이 2021년 10월 17일 답변
<resources>

    <string name="temp">TextView</string>

    <string name="app_name">gallery</string>
    <string name="app_name2">명화</string>

    <string name="title1">Starry Night</string>
    <string name="artist1">고흐</string>
    <string name="picture1">starry_night</string>

    <string name="title2">Still Life with kettle</string>
    <string name="artist2">폴 세잔</string>
    <string name="picture2">still_life_with_kettle</string>

    <string name="tag1">1</string>
    <string name="tag2">2</string>

</resources>

지금 스트링 리소스는 이런식으로 작성한 상태입니다.
여기에서 숫자 대신에 tag를 추가해주어야하는 것인가요?
MainActivity 의 22번째 라인이 어디인가요? 거기서 String을 int타입으로 변환하면서 나오는 에러같네요. 브레이크 포인트를 걸어서 디버깅을 해보세요.
MainActivity의 22번째 라인의 코드는 String tag = (String) layout.getTag(); 이것입니다.
layout.getTag()에 어떤 값이 들어있는지 디버깅 해보세요. 아무 값도 존재하지 않거나 String 타입이 아니라면 타입변환 후 문제가 생기겠죠. Integer타입이 들어있다면 String.valueOf나 "" + integerValue 등으로 타입변환을 하셔야 할 것 같은데요. (String) integerValue는 잘못된 문법으로 보입니다.
인터넷에 검색하여 디버깅하는 방법을 찾아봤는데 22번 라인에 왼쪽 라인숫자 옆 빈 공백을 클릭하여 디버깅을 하였는데 디버깅 결과가 나오지 않습니다. 이럴땐 어떻게 해야하나요? 귀중한 시간내어 답변주셔서 너무 감사한데 저가 모르는 것이 너무 많은것 같습니다. ㅜ
...