-1

캡션이있는 이미지를 표시하는 데 액티비티 중 하나를 사용하는 앱을 만들고 있습니다. 이러한 이미지는 ViewPager (한 페이지의 각 이미지)를 사용하여 표시됩니다.Android 기기를 돌릴 때 이미지를 유지하는 중

이미지를 만들고 캡션과 함께 표시하는 데 아무런 문제가 없습니다. 그러나 장치를 회전 할 때 문제가 발생합니다. 장치가 회전하면 이미지는 삭제되지만 캡션은 그대로 유지됩니다. 나는 그 이유를 알고 있다고 생각한다. (아래의 코드 단락에 설명되어있다.) 그러나 나는 그것을 풀 수 없다. 그러므로 나는이 질문을하고있다. 그런 다음 활동 코드 GalleryItemPagerActivity.java 아래

public class GalleryItemPagerActivity extends Activity { 

    private ViewPager mViewPager; 

    private NewsItem mNewsItem; 
    private int mNewsItemId; 

    ImageDownloaderThread<ImageView> mImageDownloaderThread; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 


     mViewPager = new ViewPager(this); 
     mViewPager.setId(R.id.galleryItemViewPager); 
     setContentView(mViewPager); 





     // Create a thread that will be run in the background to download images from the web for each URL 
     // 
     // IMPORTANT NOTE: 
     // We are downloading the image in the activity instead of the fragment because we are use a pager activity 
     // ... and pager activities must have the adapter in the activity rather than the fragment, which causes us to download the image here 
     // ... if we try to download in the fragment, then we will have a very complicated code that will cause too many memory leaks. 
     mImageDownloaderThread = new ImageDownloaderThread<ImageView>(new Handler()); 

     // Prepare listener to update UI when an image is downloaded 
     mImageDownloaderThread.setListener(new ImageDownloaderThread.Listener() { 

      // This method is used to update the UI when the image ready 
      public void onImageDownloaded(Bitmap image, String url, int pos, int download_image_type) { 

       // First, get the fragment by position 
       GalleryItemFragment fragment = ((GalleryItemFragmentStatePagerAdapter)mViewPager.getAdapter()).getFragment(pos); 

       // If the fragment exists 
       if (fragment != null) { 

        // Update the image 
        ImageView imageView = (ImageView) fragment.getView().findViewById(R.id.gallery_image); 
        imageView.setImageBitmap(image); 

       } 

      } 
     }); 

     // Start the background thread 
     mImageDownloaderThread.start(); 

     // Prepare the looper for the background thread 
     mImageDownloaderThread.getLooper(); 



     mNewsItemId = getIntent().getIntExtra(GalleryItemFragment.EXTRA_NEWS_ITEM_ID, 0); 
     mNewsItem = NewsItems.get(this).getNewsItem(mNewsItemId); 


     FragmentManager fm = getFragmentManager(); 
     GalleryItemFragmentStatePagerAdapter adapter = new GalleryItemFragmentStatePagerAdapter(fm); 
     mViewPager.setAdapter(adapter); 

    } 




    // Destroy the background thread when we exit the app, otherwise it will stay forever 
    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     mImageDownloaderThread.quit(); 
    } 




    // I am subclassing FragmentStatePagerAdapter so I can add the method getFragment() 
    // ... This method allows me to get the displayed fragment by position, and if it does not exist, a null is returned. 
    private class GalleryItemFragmentStatePagerAdapter extends FragmentStatePagerAdapter { 

     // A map to track current fragments. 
     private Map<Integer, GalleryItemFragment> mFragmentReferenceMap = new HashMap<Integer, GalleryItemFragment>(); 


     // Constructor 
     public GalleryItemFragmentStatePagerAdapter(FragmentManager fm) { 
      super(fm); 

     } 


     // Implementation of get count. 
     @Override 
     public int getCount() { 

      // The number of images to download is the number of our fragments 
      int count = mNewsItem.getImages().size(); 
      return count; 
     } 


     // Fragment to display, and download the main image and author avatar 
     @Override 
     public Fragment getItem(int pos) { 

      // Download this image 
      String imageUrl = mNewsItem.getImages().get(pos).getUrl(); 

      // Initiate a request to download the image at the background thread 
      mImageDownloaderThread.queueImage(imageUrl, pos, ImageDownloaderThread.DOWNLOAD_IMAGE_TYPE_MAIN); 

      // Get the fragment 
      GalleryItemFragment fragment = GalleryItemFragment.newInstance(mNewsItemId, pos); 

      // Add the fragment to our map 
      mFragmentReferenceMap.put(Integer.valueOf(pos), fragment); 



      return fragment; 

     } 


     // When a fragment is deleted, we have to remove it from the map 
     @Override 
     public void destroyItem(ViewGroup container, int pos, Object object) { 


      mFragmentReferenceMap.remove(Integer.valueOf(pos)); 

      // Remove the fragment from the map 
      mFragmentReferenceMap.remove(Integer.valueOf(pos)); 
     } 


     // Get the fragment by position (returns null if fragment does not exist) 
     public GalleryItemFragment getFragment(int key) { 
      return mFragmentReferenceMap.get(Integer.valueOf(key)); 
     } 


    } 


} 

입니다 그리고 조각의 코드가 GalleryItemFragment.java에 적합한

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <ImageView android:id="@+id/gallery_image" 
     android:layout_height="fill_parent" 
     android:layout_width="fill_parent" 
     android:scaleType="fitCenter" 
     android:background="@color/black" /> 

    <TextView android:id="@+id/gallery_caption" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="bottom" 
     android:gravity="right" 



     android:textSize="20sp" 


     android:paddingStart="@dimen/activity_horizontal_margin" 
     android:paddingEnd="@dimen/activity_horizontal_margin" 
     android:paddingBottom="@dimen/activity_vertical_margin" 

     android:textColor="@color/white" 
     android:background="@color/transparent_black_percent_50" /> 

</FrameLayout> 

:

먼저, 여기에 각각의 이미지를 표시하는 데 사용되는 내 gallery_item.xml 파일입니다

public class GalleryItemFragment extends Fragment { 

    public static final String EXTRA_NEWS_ITEM_ID = "com.myproject.android.news_item_id"; 
    public static final String EXTRA_GALLERY_ITEM_POSITION = "com.myproject.android.gallery_item_position"; 


    private int mNewsItemId; 
    private int mGalleryItemPosition; 

    private TextView mCaptionField; 


    // This is used to set attach arguments to the fragment 
    public static GalleryItemFragment newInstance (int news_item_id, int gallery_item_position) { 
     Bundle args = new Bundle(); 
     args.putInt(EXTRA_NEWS_ITEM_ID, news_item_id); 
     args.putInt(EXTRA_GALLERY_ITEM_POSITION, gallery_item_position); 

     GalleryItemFragment fragment = new GalleryItemFragment(); 
     fragment.setArguments(args); 

     return fragment; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mNewsItemId = getArguments().getInt(EXTRA_NEWS_ITEM_ID); 
     mGalleryItemPosition = getArguments().getInt(EXTRA_GALLERY_ITEM_POSITION); 

    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { 

     // inflate our xml file first 
     View v = inflater.inflate(R.layout.gallery_item, parent, false); 

     mCaptionField = (TextView)v.findViewById(R.id.gallery_caption); 
     mCaptionField.setText(NewsItems.get(getActivity()).getNewsItem(mNewsItemId).getImages().get(mGalleryItemPosition).getCaption()); 

     return v; 
    } 

} 

이제 엠.

앞에서 설명한 것처럼 장치를 회전하면 활동이 삭제되지만 조각은 그대로 유지됩니다 (수락 된 답변 here에서 설명).

또한 내 사례의 이미지가 프래그먼트가 아닌 활동에 다운로드된다는 것을 알았습니다 (페이징 활동을 사용하기 때문에 어댑터가 프래그먼트가 아닌 활동에 있어야 함).

그래서 활동이 파괴되면 이미지는 사라집니다 (그러나 캡션은 보존 된 조각의 일부이므로 유지됩니다). 따라서 이미지가없는 검은 색 페이지가되지만 캡션 만 표시됩니다.

는 지금, 나는 다른 솔루션 (예 : this one)를 읽고, 나는 AndroidManifest.xml

android:configChanges="orientation|screenSize" 

에 다음 줄을 추가하려고하지만 왼쪽으로 슬라이딩 할 때 이미지가 '불균형'보면이 훨씬 도움이되지 않았다 화면 크기를 유지하는 screenSize 속성 때문에 장치를 회전 한 직후에 우스운 이미지가 나타납니다.

지금, 나는 onSaveInstanceState()을 시도해야한다고 생각하지만 그렇게하는 방법을 모르겠다. onSaveInstanceState()을 사용하여 이미지를 저장하고 유지하려면 어떻게해야합니까? 내 액티비티 클래스의 다른 변수 (예 : mViewPager)는 저장해야합니까?

감사합니다.

답변

1

참조, 그 장치의 구성이 변경 될 때마다 활동이나 조각이 파괴 얻을 것이다 디자인에 따라 그러나 당신이 안드로이드 다음 그들에게 자신을 처리하는 경우는 파편에서 개체를 개최 조각에 setRetainInstance API를 사용할 수 있습니다,이에 추가

onSaveInstanceState() -- you can save and restore the instance stae 
onConfigurationChanged() -- you can handle the configuration changes which you have declared to handle yourself, like in your case "orientation|screenSize" 

같은 API를 사용하여 당신에게 같은 시설을 제공 할 활동이 파괴되면 당신은 그것에 대해 읽을 수 있습니다 here, 그러나이 API는 비트 맵 같은 개체를 개최 언급하지 마십시오.

이제 문제가 발생했습니다. 이것이 사용자가해야 할 일입니다. 당신이

  • 당신이 방향은 위에 제공된 정보에 의해, 다음 분리 비트 맵을 변경하는 경우, 유지하려는 객체를 보류

    1. 은 그나마 안드로이드 핸들을하자, 모든 구성을 직접 변경 처리합니다.
    2. 다운로드 한 이미지를 효율적으로 처리하기 위해 FileChache를 구현하고 이미지를 다운로드하기 전에 이미지가 이미 다운로드되었는지 확인한 다음 다시 다운로드하는 대신 동일한 이미지를 사용하여 구성이 변경되면 확인합니다. 이미지를 doanloaded.

    guthub 링크에서 확인할 수 있습니다.

  • +0

    이미지를 처리하기 위해 LruCache와 함께'onConfigurationChanged()'를 사용하여 끝내게되었습니다. – Greeso

    0

    가 귀하의 문제는 onconfiguration에 relod되어 매니페스트 파일이 같은 그 활동 파일에 권한을 부여, 변경 :

    android:configChanges="orientation|keyboard" 
    
    관련 문제