I am implementing a photo viewer which allow user to view photos in full-screen mode from a thumbnail.
My current approach is adding inflated view to WindowManager
. In the inflated view, there is a ViewPager
allowing user switch images. And I got error "java.lang.IllegalArgumentException: No view found for id"
Here is the details (a view is inflated in setActivity method and setting adapter for viewPager in openPhoto method):
public class PhotoViewer {
private static final String TAG = "PhotoViewer";
private Activity parentActivity;
private FrameLayoutTouchListener windowView;
private RelativeLayout containerView;
private WindowManager.LayoutParams windowLayoutParams;
private PhotoViewerAdapter photoAdapter;
private ViewPager viewPager;
public PhotoViewer() {
super();
}
private static volatile PhotoViewer Instance = null;
/*inflate view here*/
public void setParentActivity(Activity activity) {
if (parentActivity == activity) {
return;
}
parentActivity = activity;
windowView = new FrameLayout(activity);
containerView = (RelativeLayout) LayoutInflater.from(activity)
.inflate(R.layout.fragment_photo_viewer, null);
containerView.setFocusable(false);
windowView.addView(containerView);
windowLayoutParams = new WindowManager.LayoutParams();
windowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
windowLayoutParams.format = PixelFormat.TRANSLUCENT;
windowLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
windowLayoutParams.gravity = Gravity.TOP;
windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
viewPager = (ViewPager) containerView.findViewById(R.id.photo_viewer_view_pager);
}
/*set data and adapter for viewPager here*/
public void openPhoto (PhotoSupporter photoSupporter, int position){
try {
if (windowView.getParent() != null) {
WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
wm.removeView(windowView);
}
} catch (Exception e) {
Log.v(TAG, e.getMessage());
}
WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE);
wm.addView(windowView, windowLayoutParams);
this.photoSupporter = photoSupporter;
photoAdapter = new PhotoViewerAdapter(((FragmentActivity) parentActivity).getSupportFragmentManager(), photoSupporter);
viewPager.storeAdapter(photoAdapter);
viewPager.setCurrentItem(position);
}
/**
* Larger PhotoView
*
*
* **/
public static class PhotoViewerAdapter extends FragmentStatePagerAdapter {
private PhotoSupporter photoSupporter;
public PhotoViewerAdapter(FragmentManager fm, PhotoSupporter photoSupporter) {
super(fm);
this.photoSupporter = photoSupporter;
}
@Override
public Fragment getItem(int position) {
String src = null;
// get photo src
return PhotoViewFragment.newInstance(src);
}
@Override
public int getCount() {
Log.w(TAG, "size in adapter: " + photoSupporter.getSize());
return photoSupporter.getSize();
}
}
public static class PhotoViewFragment extends Fragment {
private String imagePath;
public PhotoViewFragment() {
}
public static PhotoViewFragment newInstance(String imagePath) {
PhotoViewFragment previewFragment = new PhotoViewFragment();
// put data
Bundle bundle = new Bundle();
bundle.putString("IMAGE_PATH",
imagePath);
previewFragment.setArguments(bundle);
return previewFragment;
}
/**
* When creating, retrieve this instance's number from its arguments.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imagePath = getArguments() != null ? getArguments().getString(
"IMAGE_PATH") : "";
Log.d("onCreate", imagePath);
}
/**
* The Fragment's UI is just a simple text view showing its instance
* number.
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ImageView imageView = new ImageView(getActivity());
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams
(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(lp);
// set image by Picasso
Picasso picassoInstance = Picasso.with(getActivity());
picassoInstance.setIndicatorsEnabled(true);
picassoInstance.load(new File(imagePath))
.error(R.drawable.ic_picture_placeholder_light2)
.fit()
.centerInside()
.into(imageView);
return imageView;
}
}
}
and here is where PhotoViewer's method is called:
public class PhotosFragment extends Fragment implements PhotoSupporter{
/*
....
*/
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
showLoading();
photosGridview = (GridView) findViewById(R.id.group_photos_gridview);
if (listPhotos == null) {
listPhotos = new ArrayList<Photo>();
}
photoListAdapter = new PhotoListAdapter(listPhotos, getActivity());
photosGridview.setAdapter(photoListAdapter);
photosGridview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
PhotoViewer.getInstance().setParentActivity(getActivity());
PhotoViewer.getInstance().openPhoto(PhotosFragment.this, position);
}
});
}
@Override
public int getSize() {
return listPhotos == null ? 0 : listPhotos.size();
}
@Override
public Photo getPhotoItem(int position) {
return listPhotos.get(position);
}
}
and here is layout of the view contaning viewPager:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/photo_viewer_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/dark_background" >
</android.support.v4.view.ViewPager>
Here is logcat:
01-14 14:12:55.271: E/AndroidRuntime(11435): FATAL EXCEPTION: main
01-14 14:12:55.271: E/AndroidRuntime(11435): java.lang.IllegalArgumentException: No view found for id 0x7f0b00df (com.newsfeed.android:id/photo_viewer_view_pager) for fragment PhotoViewFragment{537b5ec4 #8 id=0x7f0b00df}
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:903)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.ja va:1088)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:461)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentSta tePagerAdapter.java:163)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.view.ViewPager.populate(ViewPager.java:1064)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.view.ViewPager.populate(ViewPager.java:911)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1432)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.View.measure(View.java:15172)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:617)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:399)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.View.measure(View.java:15172)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.View.measure(View.java:15172)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.Choreographer.doCallbacks(Choreographer.java:555)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.Choreographer.doFrame(Choreographer.java:525)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.os.Handler.handleCallback(Handler.java:615)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.os.Handler.dispatchMessage(Handler.java:92)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.os.Looper.loop(Looper.java:137)
01-14 14:12:55.271: E/AndroidRuntime(11435): at android.app.ActivityThread.main(ActivityThread.java:4745)
01-14 14:12:55.271: E/AndroidRuntime(11435): at java.lang.reflect.Method.invokeNative(Native Method)
01-14 14:12:55.271: E/AndroidRuntime(11435): at java.lang.reflect.Method.invoke(Method.java:511)
01-14 14:12:55.271: E/AndroidRuntime(11435): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-14 14:12:55.271: E/AndroidRuntime(11435): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-14 14:12:55.271: E/AndroidRuntime(11435): at dalvik.system.NativeStart.main(Native Method)
Any solution for this problem? Thank you guys so much!
I think you are just missing a small error. Instead of this.
viewPager = (ViewPager) containerView.findViewById(R.id.photo_viewer_view_pager);
do
viewPager = (ViewPager) containerView.findViewById(R.id.photo_viewer_viewpager);
I think you are using wrong id for viewpager. Hope it will solve your problem.
I think this is because you are adding your ViewPager directly via the WindowManager. Doing so means that it won't be part of the normal Activity view hierarchy (i.e. a child of the decor view).
Activity.findViewById
(which traverses views using the decor view as the root) won't be able to locate your ViewPager.The ViewPager adapter creates Fragments and uses the ViewPager (id) as the container. When creating a Fragment, Android looks for this container via
Activity.findViewById
, but won't be able to find it and so throws this exception.It sounds like you want some kind of view that appears on top of the thumbnail grid. You could just use a properly styled Dialog(Fragment) to achieve this. The specifics of implementing that view would best be posed as a separate question.
i think you are inflating the view in setParenActivity() after findviewById() and that is the reason its not getting the view.