获取我的主屏幕小部件的大小

问题描述 投票:13回答:4

我只想知道我当前的小部件有多大。我发现了很多问题来设置最小大小,但是我不想设置它。相反,我想显示仅适合小部件的信息。

如果小部件太小,我需要隐藏一些东西,但是我需要知道它的大小。我阅读了AppWidgetProvider之类的某些类的源代码,甚至是文档。总是有关于最小或最大大小的参考,而没有当前大小的参考。

请向我指出正确的资源。

android android-widget homescreen
4个回答
10
投票

不幸的是,仍然没有API可从The AppWidget-Host获取此信息。

[您仅获得有关调整大小事件的当前大小信息(Android 4.1+),并且仅从支持此大小的启动器(例如,Sony XPeria Launcher以及某些第三方启动器)获取。

我遵循了这个stackoverflow线程和Android开发人员文档:

Determine the homescreen's appwidgets space grid size

https://developer.android.com/reference/android/appwidget/AppWidgetProvider.html#onAppWidgetOptionsChanged%28android.content.Context,%20android.appwidget.AppWidgetManager,%20int,%20android.os.Bundle%29

这是我确定小部件尺寸的代码,取自Picture Calendar 2014(Play商店):

        /* Get Device and Widget orientation. 
           This is done by adding a boolean value to 
           a port resource directory like values-port/bools.xml */

        mIsPortraitOrientation = getResources().getBoolean(R.bool.isPort);

        // Get min dimensions from provider info
        AppWidgetProviderInfo providerInfo = AppWidgetManager.getInstance(
            getApplicationContext()).getAppWidgetInfo(appWidgetId);

        // Since min and max is usually the same, just take min
        mWidgetLandWidth = providerInfo.minWidth;
        mWidgetPortHeight = providerInfo.minHeight;
        mWidgetPortWidth = providerInfo.minWidth;
        mWidgetLandHeight = providerInfo.minHeight;

        // Get current dimensions (in DIP, scaled by DisplayMetrics) of this
        // Widget, if API Level allows to
        mAppWidgetOptions = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            mAppWidgetOptions = getAppWidgetoptions(mAppWidgetManager,
                    appWidgetId);

        if (mAppWidgetOptions != null
                && mAppWidgetOptions
                        .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) > 0) {
            if (D.DEBUG_SERVICE)
                Log.d(TAG,
                        "appWidgetOptions not null, getting widget sizes...");
            // Reduce width by a margin of 8dp (automatically added by
            // Android, can vary with third party launchers)

            /* Actually Min and Max is a bit irritating, 
               because it depends on the homescreen orientation
               whether Min or Max should be used: */

            mWidgetPortWidth = mAppWidgetOptions
                    .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
            mWidgetLandWidth = mAppWidgetOptions
                    .getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
            mWidgetLandHeight = mAppWidgetOptions
                    .getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
            mWidgetPortHeight = mAppWidgetOptions
                    .getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);

            // Get the value of OPTION_APPWIDGET_HOST_CATEGORY
            int category = mAppWidgetOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);

            // If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen
            // widget (dumped with Android-L preview :-( ).
            mIsKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;

        } else {
            if (D.DEBUG_SERVICE)
                Log.d(TAG,
                        "No AppWidgetOptions for this widget, using minimal dimensions from provider info!");
            // For some reason I had to set this again here, may be obsolete
            mWidgetLandWidth = providerInfo.minWidth;
            mWidgetPortHeight = providerInfo.minHeight;
            mWidgetPortWidth = providerInfo.minWidth;
            mWidgetLandHeight = providerInfo.minHeight;
        }

        if (D.DEBUG_SERVICE)
            Log.d(TAG, "Dimensions of the Widget in DIP: portWidth =  "
                    + mWidgetPortWidth + ", landWidth = " + mWidgetLandWidth
                    + "; landHeight = " + mWidgetLandHeight
                    + ", portHeight = " + mWidgetPortHeight);

        // If device is in port oriantation, use port sizes
        mWidgetWidthPerOrientation = mWidgetPortWidth;
        mWidgetHeightPerOrientation = mWidgetPortHeight;

        if (!mIsPortraitOrientation)
        {
            // Not Portrait, so use landscape sizes
            mWidgetWidthPerOrientation = mWidgetLandWidth;
            mWidgetHeightPerOrientation = mWidgetLandHeight;
        }

在Android 4.1+上,您现在具有DIP中小部件的当前大小(用于当前设备方向)。要知道您的窗口小部件有多少个主屏幕网格单元,您必须将其除以单元格大小。默认值为74dip,但这可能会因使用不同的设备或启动器而有所不同。允许更改网格的自定义启动器对于Widget开发人员来说是一个痛苦的过程。

在Android <4.1上,无法获取当前小部件的大小。因此,最好将API级别设置为JellyBean以避免麻烦。现在应该可以...两年前,当我开始使用Widget App时,这是没有选择的。

获得有关方向更改的通知以重新绘制窗口小部件是另一个主题。

重要:如果您允许用户拥有自己的多个小部件,则必须根据他们的ID对每个人进行此计算!


0
投票

您可以将方法添加到窗口小部件提供程序,并在从API 16:开始为所有版本的Android调整大小时获取窗口小部件的大小。

    @Override
    public void onAppWidgetOptionsChanged (Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle widgetInfo) {

        int width = widgetInfo.getInt (AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
        int height = widgetInfo.getInt (AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);

    }

对于新添加的小部件,您可以通过从其布局中获取其大小并将其乘以其cols num来获得其特色:

    AppWidgetProviderInfo widgetInfo = AppWidgetManager.getInstance (context).getAppWidgetInfo (widgetId);

    private int getColsNum (int size) {
        return (int) Math.floor ((size - 30) / 70);
    }

    public int getWidthColsNum () {
        return getColsNum (widgetInfo.minWidth);
    }

    public int getHeightColsNum () {
        return getColsNum (widgetInfo.minHeight);
    }

    int width = widgetInfo.minWidth * getWidthColsNum ();
    int height = widgetInfo.minHeight * getHeightColsNum ();

获取小部件列数是从官方Android guidelines中获取的。


0
投票

获取列数/行数(科特林):

val options = appWidgetManager.getAppWidgetOptions(appWidgetId)
val minHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
val maxHeight = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)

val oneCellHeight = ViewExtensions.convertDpToPx(40f * 1, context).toInt() - (30 * 1)
val twoCellHeight = ViewExtensions.convertDpToPx(40f * 2, context).toInt() - (30 * 2)
val threeCellHeight = ViewExtensions.convertDpToPx(40f * 3, context).toInt() - (30 * 3)
val fourCellHeight = ViewExtensions.convertDpToPx(40f * 4, context).toInt() - (30 * 4)

when {
    oneCellHeight in (minHeight..maxHeight) -> {
        // 1 cell
    }
    twoCellHeight in (minHeight..maxHeight) -> {
        // 2 cells
    }
    threeCellHeight in (minHeight..maxHeight) -> {
        // 3 cells
    }
    fourCellHeight in (minHeight..maxHeight) -> {
        // 4 cells
    }
    else -> {
        // More
    }
}

class ViewExtensions {
    companion object {
        fun convertDpToPx(sp: Float, context: Context): Float {
            return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, sp, context.resources.displayMetrics)
        }
    }
}

基于,该1个单元格= 40dp

https://developer.android.com/guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size


0
投票

这里是类帮助器,以像素为单位获取小部件的大小

请注意,您应该使用应用程序上下文,否则在旋转小部件时方向将不正确

class WidgetSizeProvider(
    private val context: Context // Do not pass Application context
) {

    private val appWidgetManager = AppWidgetManager.getInstance(context)

    fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
        val isPortrait = context.resources.configuration.orientation == ORIENTATION_PORTRAIT
        val width = getWidgetWidth(isPortrait, widgetId)
        val height = getWidgetHeight(isPortrait, widgetId)
        val widthInPx = context.dip(width)
        val heightInPx = context.dip(height)
        return widthInPx to heightInPx
    }

    private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int =
        if (isPortrait) {
            getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
        } else {
            getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
        }

    private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int =
        if (isPortrait) {
            getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
        } else {
            getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
        }

    private fun getWidgetSizeInDp(widgetId: Int, key: String): Int =
    appWidgetManager.getAppWidgetOptions(widgetId).getInt(key, 0)

    private fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()

}
© www.soinside.com 2019 - 2024. All rights reserved.