Update Widget When Appearance Changes

Update Widget when appearance changes

  1. Create two screenshots (one per theme) and pass it in the entry:
struct SimpleEntry: TimelineEntry {
let date: Date
let mapScreenshots: [ColorScheme: Image]
}
struct Provider: TimelineProvider {
...

func getTimeline(in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let entry = SimpleEntry(
date: Date(),
mapScreenshots: [
// replace with actual map screenshots
.dark: Image(systemName: "plus"),
.light: Image(systemName: "minus"),
]
)
let timeline = Timeline(entries: [entry], policy: .never)
completion(timeline)
}
}

  1. Use @Environment(\.colorScheme) to react to theme changes:
struct WidgetEntryView: View {
@Environment(\.colorScheme) var colorScheme

var entry: Provider.Entry

var body: some View {
if let screenshot = entry.mapScreenshots[colorScheme] {
screenshot
}
}
}
  • iOS 14 Widget Detect System Theme Change

How to refresh Widget when Main App is used?

WidgetCenter.shared.reloadAllTimelines() is independent from the UI framework you use. You can use it from SwiftUI or UIKit.

If you're worried about making too many requests you could call that method only once your app goes to the background.

android update widget appearance

You can try this way:

public class SwitchWidget extends AppWidgetProvider {
public static String SWITCH_WIDGET_UPDATE = "MainActivity.Switch";
public static String WIFI = "wifi";

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
super.onUpdate(context, appWidgetManager, appWidgetIds);
updateSwitch1(context, appWidgetManager, appWidgetIds[0]);
}

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
super.onReceive(context, intent);
Log.d("SWitch Widget", "On Receive");

WifiManager wifiManager = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);

RemoteViews remoteViews;

AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);

if (SWITCH_WIDGET_UPDATE.equals(intent.getAction())) {
Log.d("SWitch Widget", "Widget Choose");
ComponentName thisAppWidget = new ComponentName(
context.getPackageName(), getClass().getName());

int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
for (int appWidgetID : ids) {

updateSwitch1(context, appWidgetManager, appWidgetID);
}

}

}
if (intent.getAction().equals(WIFI)) {

if(wifiManager.isWifiEnabled())
wifiManager.setWifiEnabled(false);
else
wifiManager.setWifiEnabled(true);

// appWidgetManager.updateAppWidget(1, remoteViews);
}
else if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {

remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget1);
wifiManager = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
if (wifiManager.isWifiEnabled()) {
remoteViews.setImageViewResource(R.id.button_one,
R.drawable.switch_1_wifi_on);
} else {

remoteViews.setImageViewResource(R.id.button_one,
R.drawable.switch_1_wifi_off);
}
appWidgetManager.updateAppWidget(new ComponentName(context,
SwitchWidget.class), remoteViews);

}

private void updateSwitch1(Context context,
AppWidgetManager appWidgetManager, int appWidgetId) {
// TODO Auto-generated method stub
Log.d("SWitch Widget", "Switch1");
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget1);

WifiManager wifi = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled())
remoteViews.setImageViewResource(R.id.button_one, R.drawable.switch_1_wifi_on);
else
remoteViews
.setImageViewResource(R.id.button_one, R.drawable.switch_1_wifi_off);

Intent wifiIntent = new Intent(context, SwitchWidget.class);
wifiIntent.putExtra("ID", appWidgetId);
wifiIntent.setAction(WIFI);
PendingIntent wifiPendingIntent = PendingIntent.getBroadcast(context,
0, wifiIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.button_one, wifiPendingIntent);

appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}

}

And also don't forget to add action in your manifest file and also add permissions for that.

     <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="wifi" />

iOS 14 Widget Detect System Theme Change

Although Widget views are static, you may still detect @Environment(\.colorScheme).

Here is a simple demo:

struct WidgetEntryView: View {
@Environment(\.colorScheme) var colorScheme

var entry: Provider.Entry

var bgColor: some View {
colorScheme == .dark ? Color.red : Color.orange
}

var body: some View {
ZStack {
bgColor
Text(entry.date, style: .time)
}
}
}

Note that when the system color scheme changes:

  • only your View is redrawn, the getTimeline function is not called again
  • the default colors change automatically when the system color scheme changes

Here is a GitHub repository with different Widget examples including the Environment Widget.

Swift Storyboard appearance changes don't get updated when run

You have made changes in the storyboard that involve new iOS 15 button features. Those features don't exist in iOS 13 so naturally you don't see them there.

How to change the color of a Widget based on a different Widget?

In Flutter everything is a widget and you can create your own custom widgets.
Likewise, there are concepts such as hierarchy and state.

A stateless widget is a StatelessWidget such as a label, a background, a title or whatever.

A stateful widget is a StatefulWidget is something that changes such as a switch, an animated background, a page, etc. There is also an InheritedWidget but that is another topic.

setState is used in the StatefulWidget to update the state of that widget, to update a child from the parent, you can use the properties of the child.
When setState is called, it rebuilds the widget and its children if necessary.

The Container widget has a color property.

Container(
color: colorParent,
)

Your custom widget can also have any property such as color or size or colorChild.

ChildWidget(
colorChild: colorParent,
)

When you want to access the colorChild property of a StatefulWidget you use widget.colorChild, when it has no state, you can simply use colorChild.

import 'package:flutter/material.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(),
body: Center(
child: Parent(),
),
),
);
}
}

class Parent extends StatefulWidget {
@override
ParentState createState() => ParentState();
}

class ParentState extends State<Parent> {

// Define the color in parent
Color colorParent = Colors.red;

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [

// Pass the color as a property

ChildWidget(colorChild: colorParent),
VerticalDivider(color: colorParent),
Child2Widget(colorChild: colorParent),
],
),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
label: "Tap to Blue",
icon: Icon(Icons.home),
),
BottomNavigationBarItem(
label: "Tap to Orange",
icon: Icon(Icons.dashboard),
),
BottomNavigationBarItem(
label: "Tap to Green",
icon: Icon(Icons.palette),
),
// ...
],
onTap: _onItemTap,
),
);
}

void _onItemTap(index) {
// ...
switch (index) {
case 0:
setState(() {

// Update color in parent
colorParent = Colors.blue;
});
break;
case 1:
setState(() {
colorParent = Colors.orange;
});
break;
case 2:
setState(() {
colorParent = Colors.green;
});
break;
}
}
}

class ChildWidget extends StatefulWidget {

// Define color in child
final Color colorChild;

const ChildWidget({Key key, this.colorChild}) : super(key: key);

@override
ChildWidgetState createState() => ChildWidgetState();
}

class ChildWidgetState extends State<ChildWidget> {
@override
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
// Use it
color: widget.colorChild,
child: Text('Child 1'),
);
}
}

class Child2Widget extends StatelessWidget {

// Define color in child
final Color colorChild;

const Child2Widget({Key key, this.colorChild}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,

// Use it
color: colorChild,
child: Text('Child 2'),
);
}
}

Widget changed appearance with 4.4

I don't have an answer (and I don't have enough of a reputation to post a comment). I have the same problem, although I'm creating my buttons in code. They work on devices prior to 4.4, but are dark grey and borderless on my Nexus with 4.4 and a 4.4 emulator.

I understand that 4.4 changed drawables to tone down touch feedback (see http://developer.android.com/design/patterns/new.html). Perhaps, in the process, a button style or drawable got misplaced. If so, a solution/kludge might be to copy working resources from the SDK into your project and call setBackgroundResource() to them. I haven't tried this; I'm hoping someone can come up with something more elegant and definitive.



Related Topics



Leave a reply



Submit