I have a ScrollViewer which is partly covered by an image in my Windows Phone 8 app. Now when you begin scrolling on the image it works just like when begin scrolling outside of the image. But I want to prevent the ScrolLViewer from scrolling when the drag movement starts on the image. The image is a partly transparent png file, but the same behaviour occurs when I replace it with a rectangle.
How can I do this with WP8?
You'll have to attach event handlers to the Image's MouseLeftButtonDown, MouseLeave, and MouseLeftButtonUp to disable and then re-enable the ScrollViewer's vertical/horizontal scrolling.
private void Image_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
}
private void Image_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
private void Image_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
}
Related
I have an app for test, with 3 buttons:
one for change title bar color to white
one for change title bar color to black
one for let the app title bar free to follow the Windows 10 theme color for its app title bar
Those first two buttons are ok and working, but the last one I don't know how to implement and where to put methods if necessary. I'd like, please, any help, tip or even a whole solution for the problem. Thank you in advance.
PS: would be great if title bar color can follow dark, light and even high contrast colors.
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace App7
{
public sealed partial class MainPage : Page
{
Windows.UI.ViewManagement.ApplicationViewTitleBar titleBar = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TitleBar;
public MainPage()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
titleBar.BackgroundColor = Windows.UI.Colors.White;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
titleBar.BackgroundColor = Windows.UI.Colors.Black;
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//Title bar must be free to change its own colour accord/when/same time Windows theme change
//How can I do that?
//Where the code/methods goes?
}
}
}
You could handle the ColorValuesChanged Event of the UISettings Class. This event will happen when the Windows theme color is changed. You could get the current color of the Windows theme using UISettings.GetColorValue() to check if it is in Dark mode or Light mode. Then you could change the title bar color as you want.
Here is the code:
public Windows.UI.ViewManagement.UISettings uiSettings { get; set; }
private void Button_Click(object sender, RoutedEventArgs e)
{
uiSettings = new Windows.UI.ViewManagement.UISettings();
uiSettings.ColorValuesChanged += UiSettings_ColorValuesChanged;
// if you want to stop this.
//uiSettings.ColorValuesChanged -= UiSettings_ColorValuesChanged;
}
private void UiSettings_ColorValuesChanged(Windows.UI.ViewManagement.UISettings sender, object args)
{
// happens when the windows theme is changed.
// The color you get is either black(#FF000000) for dark theme or white(#FFFFFFFF) for light theme.
Color backgroundcolor = uiSettings.GetColorValue(Windows.UI.ViewManagement.UIColorType.Background);
// change titlebar color.
Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TitleBar.BackgroundColor = backgroundcolor;
}
In my MainPage.xaml, which is a ContentPage, I have a GradientColorStack.
<local:GradientColorStack x:Name="ColorStack" StartColor="#FF0000" EndColor="#FFFF00">
This class has StackLayout as a base class and it presents a background that has a gradient color fill. I got this idea from here.
public class GradientColorStack : StackLayout
The problem is that on device orientation change, the background color fill is not re-drawn. Thus in landscape orientation there is a big gap filled with black where you can see through the GradientColorStack to the ContentPage background.
Is there a way to force the GradientColorStack to re-draw on device orientation change?
iOS Version
I added the following method to my renderer class:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
SetNeedsDisplay();
base.OnElementPropertyChanged(sender, e);
}
This causes the Draw() method of the same class to be called on a screen orientation event. In Draw() I now find the existing CAGradientLayer (if it exists) and remove it from the super layer and then just let the Draw() routine then calculate a new CAGradientLayer as usual, which it then adds to the NativeView.Layer.Sublayers collection as usual.
Thanks to #SHUBHAM SHARMA for the tip of using SetNeedsDisplay() but this post was also required to get the solution working.
Android Version
It turns out the Android version was already working to correctly redraw the gradient layer (see tutorial). I think this is because of the following method in my renderer class:
protected override void OnElementChanged(ElementChangedEventArgs<StackLayout> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
var stack = e.NewElement as GradientColorStack;
this.StartColor = stack.StartColor;
this.EndColor = stack.EndColor;
}
You can use ForceLayout() in android Renderer and SetNeedDisplay() in iOS Renderer because these function are forcefully refresh the layout.
I know that I can make a Label clickable by using TapGesture. How can I give a highlight effect when the user is tapping it? (Either changing the Label's color or changing the Background Color just like when the user taps the Toolbar Items)
You could simulate the effect with a TapGestureRecognizer by just changing the color of your label in your tapped method and back at the end.
private void OnTapped(object sender, EventArgs e)
{
var label = sender as Label;
label.TextColor = Color.Gray;
//Do Something
label.TextColor = Color.Black;
}
Although, styling a button might work better to handle the effect for you.
Here is a fix to Nick Pepper's answer, to properly restore color on UI thread.
private void OnTapped(object sender, EventArgs e)
{
var label = sender as Label;
label.TextColor = Color.Gray;
Run.Task( () => {
// Now we are on a background thread, can take as long as we want.
// ... Do Something ...
Device.BeginInvokeOnMainThread( () => {
// Now we are back on main thread, can change UI.
label.TextColor = Color.Black;
});
});
}
HOWEVER this won't change color to Gray until OnTapped fires - which is NOT the instant that user pushes down. So still isn't what user asked for.
Changing the color as soon as the user starts pushing is more involved. Might need to use Touch Tracking API.
OR use Visual State Manager.
I have to show a web browser inside a scroll viewer in windows phone application, with these requirements :
Web browser height should be adjusted based on its content.
Web browser scrolling should be disabled, ( when user scrolls within web browser, scrolling of scroll viewer should take place )
Web browser can do pinch-zoom and navigate to links inside its content.
How can I implement that? Any links or samples is greatly appreciated.
I'm using code like this. Attach events to the Border element in the Browser control tree (I'm using Linq to Visual Tree - http://www.scottlogic.co.uk/blog/colin/2010/03/linq-to-visual-tree/).
Browser.Loaded +=
(s,e)=>
{
var border = Browser.Descendants<Border>().Last() as Border;
if (border != null)
{
border.ManipulationDelta += BorderManipulationDelta;
border.ManipulationCompleted += BorderManipulationCompleted;
border.DoubleTap += BorderDoubleTap;
}
};
Further more the implementation I'm using is to prevent pinch and zoom, something you want to have working. Though this should help you in the right direction.
private void BorderDoubleTap(object sender, GestureEventArgs e)
{
e.Handled = true;
}
private void BorderManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
// suppress zoom
if (Math.Abs(e.DeltaManipulation.Scale.X) > 0.0||
Math.Abs(e.DeltaManipulation.Scale.Y) > 0.0)
e.Handled = true;
}
private void BorderManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
// suppress zoom
if (Math.Abs(e.FinalVelocities.ExpansionVelocity.X) > 0.0 ||
Math.Abs(e.FinalVelocities.ExpansionVelocity.Y) > 0.0)
e.Handled = true;
}
On Mark's direction, I used
private void Border_ManipulationDelta(object sender,
System.Windows.Input.ManipulationDeltaEventArgs e)
{
e.Complete();
_browser.IsHitTestVisible = false;
}
How can you tell whether the device is oriented vertically (portrait) or horizontally (landscape)?
Is there an API that simplifies this or do you have to make the determination "by hand" using the accelerometer?
I myself just have looked at windows 7 phones(through vs2010 express phone edition).
It seems to have in the code behind this
public MainPage()
{
InitializeComponent();
// seems to set the supported orientations that your program will support.
SupportedOrientations = SupportedPageOrientation.Portrait | SupportedPageOrientation.Landscape;
}
Then the actual form has
private void PhoneApplicationPage_OrientationChanging(object sender, OrientationChangedEventArgs e)
{
var test = e.Orientation;
}
So when the orientation changes it e.Orientation will tell you what orientation it is. Like for instance LandscapeRight.
Also you don't have to track this only via the event, you can ask for it directly from the PhoneApplicationPage instance:
private void Button_Click(object sender, RoutedEventArgs e)
{
MyCurrentOrientation.Text = this.Orientation.ToString();
}
You can also ask it through this.Orientation when your application starts so you know what the orientation is. Afther the start you can use the OrientationChanged event.
In your main:
OrientationChanged += new EventHandler<OrientationChangedEventArgs>(MainPage_OrientationChanged);
void MainPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
{
Console.WriteLine(e.Orientation.ToString());
}