24

I have an App Widget which, when it updates, fetches an image having dimensions to match the widget, and places that image into an ImageView (via RemoteViews). It works just fine.

But for devices that support rotation of the home screen (and I'm not talking about rotation of e.g. an Activity based on device orientation, but about rotation of the home screen itself) the dimensions and aspect ratio of the widget changes a bit when going from landscape to portrait and vice versa... i.e. a fixed size is not maintained.

So, my widget needs to be able to detect when the home screen rotates, and fetch a new image (or at least load a different pre-fetched image).

I can't for the life of me work out whether and how this is possible. Any clues?

drmrbrewer
  • 11,491
  • 21
  • 85
  • 181

7 Answers7

7

Use below code to detect orientation:-

    View view = getWindow().getDecorView();
    int orientation = getResources().getConfiguration().orientation;

    if (Configuration.ORIENTATION_LANDSCAPE == orientation) {
       relativeLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.log_landscape));
        imageview_Logo.setImageResource(R.drawable.log_landscape_2);
        Log.d("Landscape", String.valueOf(orientation));
        //Do SomeThing; // Landscape
    } else {
       relativeLayout.setBackgroundDrawable( getResources().getDrawable(R.drawable.login_bg) );
       imageview_Logo.setImageResource(R.drawable.logo_login);
        //Do SomeThing;  // Portrait
        Log.d("Portrait", String.valueOf(orientation));
    }
Amit Desale
  • 1,281
  • 3
  • 16
  • 43
1

You can listen for broadcast ACTION_CONFIGURATION_CHANGED which is sent by android system when the current device Configuration (orientation, locale, etc) has changed. As per documentation :

ACTION_CONFIGURATION_CHANGED :

Broadcast Action: The current device Configuration (orientation, locale, etc) has changed. When such a change happens, the UIs (view hierarchy) will need to be rebuilt based on this new information; for the most part, applications don't need to worry about this, because the system will take care of stopping and restarting the application to make sure it sees the new changes. Some system code that can not be restarted will need to watch for this action and handle it appropriately.

You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver().

This is a protected intent that can only be sent by the system.

public class YourWidgetProvider extends AppWidgetProvider {

        @Override
        public void onEnabled(Context context) {
            super.onEnabled(context);
            context.registerReceiver(mOrientationChangeReceiver,new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
        }

        @Override
        public void onDisabled(Context context) {
            context.unregisterReceiver(mOrientationChangeReceiver);
            super.onDisabled(context);
        }

        public BroadcastReceiver mOrientationChangeReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent myIntent) {
                if ( myIntent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
                    if(context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
                        // landscape orientation
                        //write logic for building remote view here
                        // buildRemoteViews();
                    }
                    else {
                        //portrait orientation
                        //write logic for building remote view here
                        // buildRemoteViews();
                    }
                }
            }
        };
    }
abhishesh
  • 3,246
  • 18
  • 20
  • The provider may be destroyed at any time - in which case your receiver would leak. Presumably later on in onDisabled it would also run into a NPE due to mOrientationChangeReceiver being null for the new provider instance. An app widget is a temporary context and so a registered receiver is not appropriate in this situation. – Tom Jun 15 '16 at 03:11
1

Since Android API 16, there is a new override that receives configuration information.

@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)
{
    int width = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
    int height = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
    int orientation = context.getResources().getConfiguration().orientation;

    if (BuildConfig.DEBUG) logWidgetEvents("UPDATE " + width + "x" + height + " - " + orientation, new int[] { appWidgetId }, appWidgetManager);

    onUpdate(context, appWidgetManager, new int[] { appWidgetId });
}

The onUpdate() can then check orientation, like this:

int rotation = context.getResources().getConfiguration().orientation;
if (rotation == Configuration.ORIENTATION_PORTRAIT)
{
    ... portrait ...
}
else
{
    ... landscape ...
}
3c71
  • 4,313
  • 31
  • 43
0

Use the onConfigurationChanged method of Activity. See the following code:

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);

// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
    Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
    Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}

Okay so for widgets we have to add our application class as below and don't forget to declare it in manifest also, the method basically sends an update broadcast to all instances of your widget.

public class MyApplication extends Application {

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // create intent to update all instances of the widget
    Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidget.class);

    // retrieve all appWidgetIds for the widget & put it into the Intent
    AppWidgetManager appWidgetMgr = AppWidgetManager.getInstance(this);
    ComponentName cm = new ComponentName(this, MyWidget.class);
    int[] appWidgetIds = appWidgetMgr.getAppWidgetIds(cm);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);

    // update the widget
    sendBroadcast(intent);
}
}

and in manifest...

<application
android:name="yourpackagename.MyApplication"
android:description="@string/app_name"
android:label="@string/app_name"
android:icon="@drawable/app_icon">

<!-- here go your Activity definitions -->

Rohit Jagtap
  • 1,660
  • 1
  • 14
  • 12
0

Check this code it works:

 myButton.setOnClickListener(new OnClickListener() {
   public void onClick(View v) {

    int rotation = getWindowManager().getDefaultDisplay()
      .getRotation();
    // DisplayMetrics dm = new DisplayMetrics();
    // getWindowManager().getDefaultDisplay().getMetrics(dm);
    int orientation;
    CharSequence text;

    switch (rotation) {
    case Surface.ROTATION_0:
     text = "SCREEN_ORIENTATION_PORTRAIT";
     break;
    case Surface.ROTATION_90:
     text = "SCREEN_ORIENTATION_LANDSCAPE";
     break;
    case Surface.ROTATION_180:
     text = "SCREEN_ORIENTATION_REVERSE_PORTRAIT";
     break;
    case Surface.ROTATION_270:
     text = "SCREEN_ORIENTATION_REVERSE_LANDSCAPE";
     break;
    default:
     text = "SCREEN_ORIENTATION_PORTRAIT";
     break;
    }

    // CharSequence text = String.valueOf(orientation);
    Toast toast = Toast.makeText(getApplicationContext(), text,
      Toast.LENGTH_SHORT);
    toast.setGravity(Gravity.CENTER | Gravity.CENTER, 10, 0);
    toast.show();

   }
  });
Androider
  • 3,833
  • 2
  • 14
  • 24
0
View view = getWindow().getDecorView();
int orientation = getResources().getConfiguration().orientation;

if (Configuration.ORIENTATION_LANDSCAPE == orientation) {
   relativeLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.log_landscape));
    imageview_Logo.setImageResource(R.drawable.log_landscape_2);
    Log.d("Landscape", String.valueOf(orientation));
    //Do SomeThing; // Landscape
} else {
   relativeLayout.setBackgroundDrawable( getResources().getDrawable(R.drawable.login_bg) );
   imageview_Logo.setImageResource(R.drawable.logo_login);
    //Do SomeThing;  // Portrait
    Log.d("Portrait", String.valueOf(orientation));
}
-1

You could checking it using the widgets width and height as done in the following code snippet:

WindowManager wm; 
Display ds; 
public boolean portrait; 

public void checkOrientation() { 
    wm = getWindowManager(); 
    ds=wm.getDefaultDisplay(); 
} 

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

    checkOrientation(); 
    if (ds.getWidth() > ds.getHeight()) { 
        // ---landscape mode--- 
        portrait = false; 
    } else if (ds.getWidth() < ds.getHeight()) { 
        // ---portrait mode--- 
        portrait = true; 
    } 
} 
Irina Avram
  • 1,492
  • 2
  • 20
  • 35