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

안녕하세요 xml로 설정한 imageView에 이미지 값을 알아오고싶습니다.

0 추천

안녕하세요 xml로 설정한 imageView에 이미지 값을 알아오고싶습니다.

위에 보시면 src로 plusbtn이라는 이미지를 넣었고 이제 저값을 해당 Activity에서 imageView를 이용해서 설정한 이미지 값을 찾고싶은데 방법을 모르겠습니다.제가 구현하고싶은 로직은 

 

 

여기서 보시면 가운데 저 이미지가 plusbtn 이미지입니다. 해당 어플리케이션에서 저 이미지를 누르면 핸드폰 갤러리안으로 들어가서 사진을 선택할수있습니다.그래서 마냐게 사진을 선택하면 이미지를 서버에 업로드해주고 사진을 선택하지 않았다면 서버에 이미지는 업로드 되지않습니다. 그래서 제가 생각한 방법은 처음 imageView설정되있는 plusbtn의 값을 가져와서 제일 하단에 있는 입력버튼을 눌렀을때 마냐게 가운데 imageview가 plusbtn인지 아닌지 plus버튼이면 서버에 업로드 해주고 plusbtn이 아니면 서버에 업로드 해주지 않습니다.그래서 저는 여기서 제일 첫번째 단계인 처음 xml에서 imageview에 src로 plusbtn갑을 설정해줬는데 Activity에서 이 설정한 이미지 값을 가져오고싶습니다.식별해줄수있따면 어떤 값이든 상관없을거같습니다.마스터 께서는 이 방법을 아십니까

2달째 코린이 (380 포인트) 님이 2021년 7월 15일 질문

2개의 답변

0 추천

뷰를 검색하는 게 아니라 이미지 정보를 검색한다고 생각하시는게 방향을 잡기에 쉽습니다. 검색된 이미지 정보를 가져와서 화면에 보여주면 되는거죠.

찾으려고 하는 이미지의 메타정보를 저장할 수 있는 클래스를 만드세요. 예를 들어 이미지 이름이나 내용을 가지고 검색을 하신다고 하면, 아래처럼 될 겁니다.

public class ImageInfo {
    private final String title;
    private final String description;
    private final String url;

    public ImageInfo(String title, String description, String url) {
        this.title = title;
        this.description = description;
        this.url = url;
    }

    // getters
}

public class ImageSearchCriteria {
    private final String title;
    private final String description;
    // Contructor, getters
}

public class ImageSearch {
    private final List<ImageInfo> images = new ArrayList<>();

    // getter

   public List<ImageInfo> searchBy(ImageSearchCriteria criteria) {
         List<ImageInfo> result = new ArrayList<>();
         for (ImageInfo image: images) {
             if (!criteria.getTitle().isEmpty() && criteria.getTitle().contains(image.getTitle()) {
                  result.add(image);
             }

              if (!criteria.getDescription().isEmpty() && criteria.getDescription().contains(image.getDescription()) {
                  result.add(image);
             }
         }
         return result;
   }
}

 

위와 같이 searchBy로 검색된 결과를 액티비티나 프레그먼트서 받아서 해당 뷰는 RecyclerView같은 데에 검색결과를 보여주면 될 것 같습니다.

검색로직은 설명을 위해 단순화 한거구요, 향상시킬 부분이 많습니다. 예를 들면 Java8의 stream API가 사용가능한 상황이시면 stream API를 쓰시는게 좋구요. 조건에 따른 검색 로직도 좀 더 캡슐화가 가능할 것으로 보입니다.

spark (227,470 포인트) 님이 2021년 7월 15일 답변
코린이여서 어느정도 이해가 안되는 부분도 있지만 이미지 정보를 저장하는 클래스를 만들어서 필요할때 꺼내써라 요약하면 이런뜻인가요?그런데 저는 ImageView에 내장된 이미지를 가져와야합니다.왜냐면 imageview에 넣어줄 이미지와 현재 imageview에 내장된 이미지를 비교를 해야되는데 이걸 수동으로 제가 저장해준다고 해도 imageView에 image가 바뀌었는지 바뀌지않았는지 알수있나요?어렵네요....
그럼 ImageInfo에 bitmap에 관련된 정보를 저장하세요. file checksum 등을 이용하시면 두 파일이 같은지 비교할 수 있을 거구요. 만약 pixel 단위의 비교가 필요하시면 https://developer.android.com/reference/android/graphics/Bitmap#sameAs%28android.graphics.Bitmap%29
Bitmap.sameAs가 있네요.
한번 시도해볼게요.답변 감사합니다.
0 추천

질문이 없데이트 된 것 같네요...원하는 기능을 보면, 굳이 비트맵 자체를 비교하실 필요는 없어 보이네요. 단순히 입력한 내용을 받아서 서버로 올려주면 되는 기능같은데요. 
앞에 말씀드렸다 시피 이미지에 정보를 같는 클래스를 하나 만드시고 ID필드와 Image filePath필드를 추가하세요. 

public class ImageInfo {
    private final String id;
    private final String title;
    private final String description;
    private final String filePath; //Uri 를 사용하실 수도 있을 거예요
 
    public ImageInfo(String id, String title, String description, String filePath) {
        this.id = id;
        this.title = title;
        this.description = description;
        this.filePath = filePath;
    }
 
    // getters

   @Override
  public boolean equals(Object other) {
      if (other == null || other instanceof ImageInfo) return false;
      
     return this.id != null && !this.id.isEmpty() && this.id.equals(((ImageInfo) other).id);
  }
  
  @Override
  public int hashCode() {
       return id != null && id.isEmpty() ?: Objects.hasCode(this) : id.hashCode();
  }

  public Boolean actuallyChanged(ImageInfo oldItem) {
        return  isSameContent(oldItem.id, this.id) &&
                    isSameContent(oldItem.title, this.title) &&
                    isSameContent(oldItem.description, this.description) &&
                    isSameContent(oldItem.filePath, this.filePath);
  }
}

public static boolean isSameContent(String oldItem, String newItem) {
     return oldItem != null && !oldItem.isEmpty() && oldItem.equals(newItem);
}

 

id는 서버에서 식별되는 고유값이 될거구요. 새로운 입력이라면 없을 거구, 업데이트라면 존재하겠죠.
filePath는 사용자가 선택한 이미지에 대한 파일이름(경로포함)을 보관합니다. 만약 업데이트 모드라면 서버에 보관된 파일이름으로 초기화가 되어있겠죠.

만약 사용자의 입력이 실제로 변경이 된 것인지까지 체크하시려면 이 클래스의 인스터스를 두개 만드세요. 하나는 업데이트 모드에서 서버에 있는 정보를 가지고 있는 클래스, 다른 하나는 사용자의 입력을 받는 클래스. 이 두개를 비교하셔서 실제 변경여부를 파악하시면 됩니다.

이미지가 아무 것도 없을 때 place holder를 보여주시는 거는 사용자 입력용 ImageInfo class의 filePath가 아무 것도 없을 때 해주시면 됩니다.

void setImage(ImageInfo imageInfo) {
   if (TextUtils.isEmpty(imageInfo.filePath)) {
         showPlaceHolder();
         return;
   } 

   boolean isUpdateMode = !TextUtils.isEmpty(imageInfo.id)
   if (isUpdateMode) {
        //업데이트 모드일 때는 filePath는 아마도 이미지 URL이겠죠.
        Glide.... //Glide같은 라이브러리를 사용하는 것이 편합니다.
        return;
   }
  
  Glide... // 로컬 이미지를 보여주면 됩니다. 
}

위의 코드는 그냥 설명을 위해 작성한 것 뿐이구요.  filePath가 데이터의 저장여부에 따라 URL이나 local file path가 될 수 있기 때문에 이 부분은 부모 클래스를 하나 만드셔서 자식 클래스를 두개 만드시거나 enum 같은 걸로 종류를 구분하시면 처리하시면 좋을 듯 합니다.

public interface class ImageFilePath {
     String getFilePath();
}

public class LocalFilePath implements ImageFilePath {
    ...
} 


public class LocalFilePath implements RemoteFilePath {
    ...
} 

// enum을 사용할 수도 있을 듯
public enum ImagePathType {
    LOCAL,
    REMOTE
}

public class ImageFilePath {
     private final pathType: ImagePathType
     private final String filePath;

    // Constructor
   
    public static createLocalPath(filePath) {
        return new ImageFilePath(ImagePathType.LOCAL, filepath);
    }

    public static createRemotePath(filePath) {
        return new ImageFilePath(ImagePathType.REMOTE, filepath);
    }
}

 

잘 살펴보시면 많은 부분은 캡슐화 하거나 중복을 줄이실 수 있을 겁니다.

spark (227,470 포인트) 님이 2021년 7월 16일 답변
...