Navigation Architecture Component - BottomNavigationView lock destination - android-navigationview

How can I lock a destination navigation when I need to check an user subscription?
navController.addOnDestinationChangedListener { controller, destination, args ->
if(user_is_not_subscribed)) {
// lock controller navigation and stay in this fragment
} else {
// continue to navigate to destination fragment
}
}

Related

How to change a property binding during an element creation in QML?

Suppose I have a custom CheckBox:
//MyCheckBox.qml
CheckBox {
required property QtObject proxy
checked: proxy.value
Binding {
target: proxy
property: "value"
value: checked
}
}
So the checked status of the MyCheckBox bound to the value property of my object (proxy) and vise-versa, i.e. I have a two-way binding.
I am using my custom checkbox as follows:
//My window
Item {
...
MyCheckBox {
id: ordinaryCheck
proxy: ...
}
...
}
Everything works as expected. But what if I need to invert the logic for some instance of MyCheckBox: when proxy.value is true the checkbox is unchecked, and when proxy.value is false the checkbox is checked ? But this, ofc, doesn't work as I have a binding loop here if I try to do this:
Item {
...
MyCheckBox {
id: invertedCheck
proxy: ...
checked: !proxy.value
Binding {
target: proxy.value
property: "value"
value: !checked
}
}
The Qt bindings are also not an option:
//MyCheckBox.qml
CheckBox {
required property QtObject proxy
checked: proxy.value
Component.onCompleted {
property.value = Qt.binding(function() { return checked });
}
}
I have the same binding loop error in this case.
So what is my option to reach the goal, how to alternate the binding at the moment of instantiation ?
Update 1
Here is my PropertyProxy::setValue member function:
void setValue( const QVariant& v )
{
if( v != value() )
{
//do some stuff
emit valueChanged();
}
}
If you're concerned about a potential binding loop, it is a potential candidate to rewrite it as an imperative implementation, e.g.
CheckBox {
required property QtObject proxy
onCheckedChanged: {
if (proxy && proxy.value !== checked) {
proxy.value = checked;
}
}
property bool proxyValue: proxy && proxy.value ? true : false
onProxyValueChanged: {
if (checked !== proxyValue) {
checked = proxyValue;
}
}
}
Your first version might also technically be a binding loop but is not detected as such.
You want to bind your checkbox value to your proxy value, and when the user toggles the checkbox you want to modify the proxy value.
To avoid binding loops, use specific interaction signals for each component, not generic onChanged signal. The former will fire only when the user interact with the UI, the latter will fire every time, even when the changes come from a backend change, leading to a potential binding loop.
In your case you want the toggled signal:
//MyCheckBox.qml
CheckBox {
required property QtObject proxy
checked: proxy.value
onToggled: proxy.value = checked
}
Note that this only works with QQC2 since they are not breaking the checked: proxy.value binding when the user toggles the checkbox, but still change the checked property value, hoping for an eventual resolution.

How to ensure only one document in document group application

I am using DocumentGroup to handle documents for me. Unfortunately its behavior is very different on BigSur I have to support when multiple documents are opened. Is there a way to ensure that pervious documents closes before opening a new one? The code snippet is below:
struct DocumentScene: Scene, Equatable {
var body: some Scene {
DocumentGroup(newDocument: V_WorkflowDocument()) {
file in
GeometryReader{
geometry in
ContentView(document: file.$document)
}
}
.commands {
CommandMenu("Run") {
RunCommand()
}
}
}

How to use #FocusedBinding

I've tried, without success, to use the new property wrapper #FocusedBinding.
The code example given here by a Frameworks Engineer, and placed below, during beta 1 period for iOS 14 and Big Sur compiles, but it doesn't seem to work for both OSs, for enabling the keyboard shortcuts.
Does anyone knows if something changed in the meantime, and how, or is something still under development?
// This example runs on macOS, iOS, and iPadOS.
//
// Big Sur Seed 1 has some known issues that prevent state-sharing between
// windows and the main menu, so this example doesn't currently behave as
// expected on macOS. Additionally, the Commands API is disabled on iOS in Seed
// 1. These issues will be addressed in future seeds.
//
// The Focused Value API is available on all platforms. The Commands and
// Keyboard Shortcut APIs are available on macOS, iOS, iPadOS, and
// tvOS—everywhere keyboard input is accepted.
#main
struct MessageApp : App {
var body: some Scene {
WindowGroup {
MessageView()
}
.commands {
MessageCommands()
}
}
}
struct MessageCommands : Commands {
// Try to observe a binding to the key window's `Message` model.
//
// In order for this to work, a view in the key window's focused view
// hierarchy (often the root view) needs to publish a binding using the
// `View.focusedValue(_:_:)` view modifier and the same `\.message` key
// path (anologous to a key path for an `Environment` value, defined
// below).
#FocusedBinding(\.message) var message: Message?
// FocusedBinding is a binding-specific convenience to provide direct
// access to a wrapped value.
//
// `FocusedValue` is a more general form of the property wrapper, designed
// to work with all value types, including bindings. The following is
// functionally equivalent, but places the burden of unwrapping the bound
// value on the client.
// #FocusedValue(\.message) var message: Binding<Message>?
var body: some Commands {
CommandMenu("Message") {
Button("Send", action: { message?.send() })
.keyboardShortcut("D") // Shift-Command-D
.disabled(message?.text.isEmpty ?? true)
}
}
}
struct MessageView : View {
#State var message = Message(text: "Hello, SwiftUI!")
var body: some View {
TextEditor(text: $message.text)
.focusedValue(\.message, $message)
.frame(idealWidth: 600, idealHeight: 400)
}
}
struct Message {
var text: String
// ...
mutating func send() {
print("Sending message: \(text)")
// ...
}
}
struct FocusedMessageKey : FocusedValueKey {
typealias Value = Binding<Message>
}
extension FocusedValues {
var message: FocusedMessageKey.Value? {
get { self[FocusedMessageKey.self] }
set { self[FocusedMessageKey.self] = newValue }
}
}

How to navigate To and Back from Push Notification setup Page after user enabled it

I used below code to detect if user has enabled push notification.
**Problem**.
1) How to open or navigate to the Push Notification setting Page in the phone
2) How to return from this Push Notification page after user enabled it or
how user return to previous page if decide to enable later.
VC_Check --> Push Notification settings
in VC_check:
if UIApplication.shared.isRegisteredForRemoteNotifications {
print("YES")
// goto other VC
} else {
// goto Phone setting page
}
//-- I dont want this Pop Up to enable Push Notification:
// detected not enabled, use below pop Up
pageUIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
Please help.
Thanks
You can ask to enable push notification like this:
func requestNotificationPermission() {
let app = UIApplication.shared
// --- from right here
if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// For iOS 10 data message (sent via FCM)
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
app.registerUserNotificationSettings(settings)
}
app.registerForRemoteNotifications()
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization.
// DO SOMETHING HERE AFTER USER AUTHORIZES, CALL A FUNCTION TO RELOAD VIEW?
}
app.registerForRemoteNotifications()
} else {
// Fallback on earlier versions
}
}
To check if user has granted permission use this:
func checkNotificationStatus() {
let current = UNUserNotificationCenter.current()
current.getNotificationSettings(completionHandler: { (settings) in
if settings.authorizationStatus == .notDetermined {
// Notification permission has not been asked yet, go for it!
print("Not yet asked for permission")
}
if settings.authorizationStatus == .denied {
// Notification permission was previously denied, go to settings & privacy to re-enable
print("Permission denied")
}
if settings.authorizationStatus == .authorized {
// Notification permission was already granted
print("Permission Granted")
}
})
}

Disable rotation for one UITabbar item

I have a uitabbarcontroller with 4 tab bar items and each tab bar item has a uinavigationcontroller.
I needed to lock the orientation of one uitabbar item only to Portrait. So i implemented the following code:
Created a custom tab bar controller and added the following code in it:
MainTabBarController.m
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// You do not need this method if you are not supporting earlier iOS Versions
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
-(NSUInteger)supportedInterfaceOrientations
{
if (self.selectedViewController)
return [self.selectedViewController supportedInterfaceOrientations];
return UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotate
{
return YES;
}
Created a custom navigation controller to use in one of the uitabbaritems and added the following code in it:
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return YES;
}
and for the uiviewcontroller in the custom navigation controller i added the following code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
The above code works fine. My issue is, if you go to the tabbar item (whose orientation is locked to Protrait) when the device is already in Landscape mode the orientation changes to Landscape. Can anyone please help me how to solve my issue.
Thanks,
Anand.
FYI!!!
I've found a way for my problem. I added the following function to the viewcontroller for which i want the display only in protrait mode:
-(void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
{
if ([[UIDevice currentDevice] respondsToSelector:#selector(setOrientation:)])
{
int orientationPortrait = UIInterfaceOrientationPortrait;
NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:#selector(setOrientation:)];
NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
[invo setTarget:[UIDevice currentDevice]];
[invo setSelector:#selector(setOrientation:)];
[invo setArgument:&orientationPortrait atIndex:2];
[invo invoke];
}
}
}