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
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
IsImageDownloaded
(Boolean)OnInstanceSave()
method and capture the current random number and the image status.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.onClick()
method and also in the if
Condition.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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With