Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set imageview after orientation change

I have the following code, which is working perectly fine till I rotate my phone. Then I have to click again to load an image, I understand that when we rotate the activity restarts and we have some methods to store the state and restore it, but in my case as you can see that the img file is in a string as it is generated at random. So how can I make use of onConfigurationChanged (which seems easy to understand) to restore the previous image before rotation?

public class HomeScreen extends Activity {

    protected ImageView imgView;
    protected String str;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_screen);
        final Random rnd = new Random();
        ActionBar actionBar = getActionBar();
        actionBar.hide();

        imgView = (ImageView) findViewById(R.id.imgRandom);

        if (savedInstanceState != null) {
            str = savedInstanceState.getString("param");
            imgView.setImageDrawable
                    (
                            getResources().getDrawable(getResourceID(str, "drawable", getApplicationContext()))
                    );




            imgView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {



                   // final ImageView img = (ImageView) findViewById(R.id.imgRandom);
                    // I have 3 images named img_0 to img_2, so...
                    str = "img" + rnd.nextInt(9);
                    imgView.setImageDrawable
                            (
                                    getResources().getDrawable(getResourceID(str, "drawable", getApplicationContext())));


                }


            });


        }
    }

    protected void onSaveInstanceState(Bundle savedInstanceStat) {
        super.onSaveInstanceState(savedInstanceStat);
        savedInstanceStat.putString("param", str);
    }

When I rotate it is crashing and also on load OR onClick no images are loading..

> 07-07 21:11:32.950: I/InputReader(468): Device reconfigured: id=1,
> name='Genymotion Virtual Input', size 1080x1920, orientation 0, mode
> 1, display id 0 07-07 21:11:32.950: I/ActivityManager(468): Config
> changes=480 {1.0 310mcc260mnc en_US ?layoutDir sw360dp w360dp h567dp
> 480dpi nrml port finger qwerty/v/v dpad/v s.14} 07-07 21:11:33.081:
> W/ResourceType(1861): Too many attribute references, stopped at:
> 0x01010034 07-07 21:11:33.081: W/ResourceType(1861): Too many
> attribute references, stopped at: 0x01010034 07-07 21:11:33.082:
> D/AndroidRuntime(1861): Shutting down VM 07-07 21:11:33.083:
> E/AndroidRuntime(1861): FATAL EXCEPTION: main 07-07 21:11:33.083:
> E/AndroidRuntime(1861): Process:
> app.motivation.techiequickie.ypb.motivation, PID: 1861 07-07
> 21:11:33.083: E/AndroidRuntime(1861): java.lang.RuntimeException:
> Unable to start activity
> ComponentInfo{app.motivation.techiequickie.ypb.motivation/app.motivation.techiequickie.ypb.motivation.HomeScreen}:
> java.lang.NullPointerException: name is null 07-07 21:11:33.083:
> E/AndroidRuntime(1861):   at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> android.app.ActivityThread.access$900(ActivityThread.java:151) 07-07
> 21:11:33.083: E/AndroidRuntime(1861):     at
> android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> android.os.Handler.dispatchMessage(Handler.java:102) 07-07
> 21:11:33.083: E/AndroidRuntime(1861):     at
> android.os.Looper.loop(Looper.java:135) 07-07 21:11:33.083:
> E/AndroidRuntime(1861):   at
> android.app.ActivityThread.main(ActivityThread.java:5254) 07-07
> 21:11:33.083: E/AndroidRuntime(1861):     at
> java.lang.reflect.Method.invoke(Native Method) 07-07 21:11:33.083:
> E/AndroidRuntime(1861):   at
> java.lang.reflect.Method.invoke(Method.java:372) 07-07 21:11:33.083:
> E/AndroidRuntime(1861):   at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 07-07
> 21:11:33.083: E/AndroidRuntime(1861): Caused by:
> java.lang.NullPointerException: name is null 07-07 21:11:33.083:
> E/AndroidRuntime(1861):   at
> android.content.res.Resources.getIdentifier(Resources.java:2034) 07-07
> 21:11:33.083: E/AndroidRuntime(1861):     at
> app.motivation.techiequickie.ypb.motivation.HomeScreen.getResourceID(HomeScreen.java:148)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> app.motivation.techiequickie.ypb.motivation.HomeScreen.onCreate(HomeScreen.java:35)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> android.app.Activity.performCreate(Activity.java:5990) 07-07
> 21:11:33.083: E/AndroidRuntime(1861):     at
> android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
> 07-07 21:11:33.083: E/AndroidRuntime(1861):   ... 11 more 07-07
> 21:11:33.084: W/ActivityManager(468):   Force finishing activity 1
> app.motivation.techiequickie.ypb.motivation/.HomeScreen
like image 302
JackyBoi Avatar asked Jul 05 '15 08:07

JackyBoi


3 Answers

It looks like the main issue is that your call to imgView.setOnClickListener() was nested inside your if (savedInstanceState != null) case.

I got your code working by un-nesting the click listener, and adding an underscore to the resource name to look for. I used nine images, named img_0.png through img_8.png and put then in the drawable folder.

I also added code that loads a random image on startup.

After that it successfully loads another random image on click. I also tested screen rotation, and your existing code works just fine, it kept the current image present no matter how many times I rotated the screen.

Here is the fully working and tested code:

public class HomeScreen extends Activity {

    protected ImageView imgView;
    protected String str;

    @Override
    protected void onCreate(final Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_screen);
        final Random rnd = new Random();
        //ActionBar actionBar = getActionBar();
        //actionBar.hide();

        imgView = (ImageView) findViewById(R.id.imgRandom);


        if (savedInstanceState != null) {
            str = savedInstanceState.getString("param");
            Log.d("image screen rotation", str);
            imgView.setImageDrawable
                    (
                            getResources()
                            .getDrawable(getResourceID(str, "drawable", getApplicationContext()))
                    );
        }
        else{
            str = "img_" + rnd.nextInt(9);
            Log.d("image startup", str);
            imgView.setImageDrawable(
                    getResources()
                            .getDrawable(getResourceID(str, "drawable", getApplicationContext())));
        }

        imgView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                // final ImageView img = (ImageView) findViewById(R.id.imgRandom);
                // I have 3 images named img_0 to img_2, so...
                str = "img_" + rnd.nextInt(9);
                Log.d("image click", str);
                imgView.setImageDrawable(
                         getResources()
                         .getDrawable(getResourceID(str, "drawable", getApplicationContext())));

            }
        });


    }

    protected final static int getResourceID
            (final String resName, final String resType, final Context ctx)
    {
        final int ResourceID =
                ctx.getResources().getIdentifier(resName, resType,
                        ctx.getApplicationInfo().packageName);
        if (ResourceID == 0)
        {
            throw new IllegalArgumentException
                    (
                            "No resource string found with name " + resName
                    );
        }
        else
        {
            return ResourceID;
        }
    }


    @Override
    protected void onSaveInstanceState(Bundle savedInstanceStat) {
        super.onSaveInstanceState(savedInstanceStat);
        savedInstanceStat.putString("param", str);
    }
}

Resulting logs from running the app, clicking on the ImageView to change the image, and then rotating the screen:

 D/image startup﹕ img_8
 D/image screen rotation﹕ img_8
 D/image screen rotation﹕ img_8
 D/image click﹕ img_3
 D/image screen rotation﹕ img_3
 D/image screen rotation﹕ img_3
 D/image screen rotation﹕ img_3
 D/image screen rotation﹕ img_3
 D/image click﹕ img_7
 D/image screen rotation﹕ img_7
 D/image screen rotation﹕ img_7
 D/image screen rotation﹕ img_7
 D/image screen rotation﹕ img_7
 D/image screen rotation﹕ img_7
 D/image screen rotation﹕ img_7
like image 189
Daniel Nugent Avatar answered Sep 21 '22 17:09

Daniel Nugent


  1. Create two class level variables to store current random number and to store image status eg:- IsImageDownloaded (Boolean)
  2. Override the OnInstanceSave() method and capture the current random number and the image status.
  3. (When you rotate the device the onCreate() will be called again) In onCreate() check whether isImageDownloaded true or false (If condition). If it is true, then get the captured random number and display the image again using this random number.
  4. You can create a separate method to load the image for a specific random number and you can use this method in onClick() method and also in the if Condition.
like image 25
sivaram gogineni Avatar answered Sep 19 '22 17:09

sivaram gogineni


Use this in your manifest.

    <activity
        android:name="youractivity"
        android:configChanges="keyboardHidden|screenSize|orientation" >
    </activity>

This will handle the orientation change on its own. And remove the savedInstance coding

like image 30
Bunny Avatar answered Sep 17 '22 17:09

Bunny