How to have a custom side bar slide from right in your metro app? - xaml

I am developing a metro app where , I want to have a customized bar slide when the user clicks on something in the screen.
This is what i am talking about :-
--------------
| | |
| | | <----
| | |
---------------
main screen side
bar
In this side bar i want have some simple controls like image and text block etc..
1) How can i do this , any help would be appreciated
2) Its not against metro principles right ?

You could try to leverage a flyout like the settings flyout. You might want to look at Callisto.
You could otherwise include a Xaml element that above all others and toggle it's visibility along with a positioning right on the screen. How to position depends on what root element you're using. For positioning an element in a canvas add Canvas.Right="0" to the child element.

You can use PopUp.
have a look at this example,
http://code.msdn.microsoft.com/windowsapps/App-settings-sample-1f762f49

you can use following helper
WinRT Flyout Helper
public class FlyoutHelper
{
protected Popup m_Popup = new Popup();
public Popup Show(Popup popup, FrameworkElement button, double offset = 35d)
{
if (popup == null)
throw new Exception("Popup is not defined");
m_Popup = popup;
if (button == null)
throw new Exception("Button is not defined");
if (double.IsNaN(offset))
throw new Exception("Offset is not defined");
var _Child = popup.Child as FrameworkElement;
if (_Child == null)
throw new Exception("Popup.Child is not defined");
if (double.IsNaN(_Child.Height))
throw new Exception("Popup.Child.Height is not defined");
if (double.IsNaN(_Child.Width))
throw new Exception("Popup.Child.Width is not defined");
// get position of the button
var _Page = Window.Current.Content as Page;
var _Visual = button.TransformToVisual(_Page);
var _Point = _Visual.TransformPoint(new Point(0, 0));
var _Button = new
{
Top = _Point.Y,
Left = _Point.X,
Width = button.ActualWidth,
Height = button.ActualHeight,
};
// determine location
var _TargetTop = (_Button.Top + (_Button.Height / 2)) -
_Child.Height - offset;
var _TargetLeft = (_Button.Left + (_Button.Width / 2)) -
(_Child.Width / 2);
if ((_TargetLeft + _Child.Width) > Window.Current.Bounds.Width)
_TargetLeft = Window.Current.Bounds.Width - _Child.Width - offset;
if (_TargetLeft < 0)
_TargetLeft = offset;
// setup popup
popup.VerticalOffset = _TargetTop;
popup.HorizontalOffset = _TargetLeft;
// add pretty animation(s)
popup.ChildTransitions = new TransitionCollection
{
new EntranceThemeTransition
{
FromHorizontalOffset = 0,
FromVerticalOffset = 20
}
};
// setup
m_Popup.IsLightDismissEnabled = true;
m_Popup.IsOpen = true;
// handle when it closes
m_Popup.Closed -= popup_Closed;
m_Popup.Closed += popup_Closed;
// handle making it close
Window.Current.Activated -= Current_Activated;
Window.Current.Activated += Current_Activated;
// return
return m_Popup;
}
protected void Current_Activated(object sender, WindowActivatedEventArgs e)
{
if (m_Popup == null)
return;
if (e.WindowActivationState == CoreWindowActivationState.Deactivated)
m_Popup.IsOpen = false;
}
protected void popup_Closed(object sender, object e)
{
Window.Current.Activated -= Current_Activated;
if (m_Popup == null)
return;
m_Popup.IsOpen = false;
}
}

For this you can use CharmFlyout.
Here is the sample code http://code.msdn.microsoft.com/windowsapps/CharmFlyout-A-Metro-Flyout-25fe53b6

Related

displaying alert dialog in the correct location within a recyclerview

I'm making a custom button that when you long press on it a dialog will appear with a list of options to choose from.
The custom button works as it should, however, I'm having some trouble wrangling the dialog to show up exactly where I want it to.
this is the code that displays the dialog.
private void ShowReactionsDialog()
{
var context = Context;
var inflater = (LayoutInflater) context.GetSystemService(Context.LayoutInflaterService);
var dialogView = inflater.Inflate(Resource.Layout.react_dialog_layout, null);
var linearLayoutManager = new LinearLayoutManager(context)
{
Orientation = LinearLayoutManager.Horizontal
};
var adapter = new ReactionAdapter(_reactionList);
adapter.OnItemClicked += (sender, currentReaction) =>
{
UpdateReactButtonByReaction(currentReaction);
_reactAlertDialog.Cancel();
};
var rvReactions = dialogView.FindViewById<RecyclerView>(Resource.Id.reaction_rvReactions);
rvReactions.HasFixedSize = true;
rvReactions.SetLayoutManager(linearLayoutManager);
rvReactions.SetItemAnimator(new DefaultItemAnimator());
rvReactions.SetAdapter(adapter);
var dialogBuilder = new AlertDialog.Builder(context);
dialogBuilder.SetView(dialogView);
_reactAlertDialog = dialogBuilder.Create();
_reactAlertDialog.RequestWindowFeature((int)WindowFeatures.NoTitle);
var window = _reactAlertDialog.Window;
window.SetBackgroundDrawableResource(Resource.Drawable.react_dialog_shape);
window.SetDimAmount(0);
// Setup dialog gravity and dynamic position
var windowManagerAttributes = window.Attributes;
windowManagerAttributes.Gravity = GravityFlags.AxisSpecified;
windowManagerAttributes.X = (int) GetX() + (Width / 2);
windowManagerAttributes.Y = (int) GetY() + (Height / 2);
_reactAlertDialog.Show();
var dialogWidth = GetIconSize() * _reactionList.Count;
if (dialogWidth > GetScreenMaxWidth())
{
dialogWidth = GetScreenMaxWidth();
}
window.SetLayout(dialogWidth, ViewGroup.LayoutParams.WrapContent);
}
I've tried messing with the gravity and the X & Y coordinates but it just wants to either go too high up or too low down, there's no consistent location it's sticking to. I want it to be above the button that's getting long tapped.
You can use the following code to make the AlertDialog show above the button.
int[] location = new int[2];
AndroidX.AppCompat.App.AlertDialog alertDialog = builder.Create();
Window window = alertDialog.Window;
WindowManagerLayoutParams attributes = window.Attributes;
//Get the location of the button and location[0] is X and location[1] is Y
button.GetLocationInWindow(location);
//Set the height of the AlertDialog
int height = 400;
int a = button.Height / 2;
int c = location[1];
//Get the distance of top
attributes.Y = c - a - height;
window.Attributes = attributes;
//Set the AlertDialog location according to the distance of top
window.SetGravity(GravityFlags.Top);
alertDialog.Show();
//Set the Width and Hight of the AlertDialog
alertDialog.Window.SetLayout(800, height);

How to show a badges count of ToolBarItem Icon in Xamarin Forms

It is not about how to show notification badges nor it's about to show toolbar item icon. It is clear question that how to show a badges count on a toolbar item icon. ?
I am sharing code to create ToolbarItem with icon in XF content page:
In cs File:
ToolbarItem cartItem = new ToolbarItem();
scanItem.Text = "My Cart";
scanItem.Order = ToolbarItemOrder.Primary;
scanItem.Icon = "carticon.png";
ToolbarItems.Add(cartItem );
In Xaml File:
<ContentPage.ToolbarItems>
<ToolbarItem Text="Cart" Priority="0" x:Name="menu1">
</ToolbarItem>
</ContentPage.ToolbarItems>
Now I want to Place a badge count on the above added tool bar item icon. How it can be achieved ?
Placing badge icon's in the native toolbars is actually more effort than its worth. If I need a badge icon, I remove the navigation page.
NavigationPage.SetHasNavigationBar(myPageInstance, false);
Then I create my own toolbar from scratch. In this toolbar, I can overlay an image in there, you can also place a number in it as needed. For example.
<Grid>
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding IconCommand}" />
</Grid.GestureRecognizers>
<iconize:IconImage
Icon="fa-drawer"
IconColor="white"
IconSize="20" />
<Grid Margin="15,-15,0,0">
<iconize:IconImage Grid.Row="0"
HeightRequest="40"
WidthRequest="40"
Icon="fa-circle"
IconColor="red"
IsVisible="{Binding IsCircleVisible}"
IconSize="10" />
</Grid>
</Grid>
I use Iconize wtih FontAwesome for the icons
With the help of Xamarin Forum Discussion, I have achieved it. Read ad understand the complete discussion before implement it. Thank you "Slava Chernikoff", "Emanuele Sabetta", "Mirza Sikander", "Satish" to discuss and yours share code.
Setp 1: Create a Helper Class in PCL and install NGraphics package from nugget.
public class CartIconHelper
{
private static Graphic _svgGraphic = null;
public const string ResourcePath = "ToolBarAndroidBadge.Resources.cartIcon.svg";
private static PathOp[] RoundRect(NGraphics.Rect rect, double radius)
{
return new PathOp[]
{
new NGraphics.MoveTo(rect.X + radius, rect.Y),
new NGraphics.LineTo(rect.X + rect.Width - radius, rect.Y),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + rect.Width, rect.Y + radius)),
new NGraphics.LineTo(rect.X + rect.Width, rect.Y + rect.Height - radius),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + rect.Width - radius, rect.Y + rect.Height)),
new NGraphics.LineTo(rect.X + radius, rect.Y + rect.Height),
new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X, rect.Y + rect.Height - radius)),
new NGraphics.LineTo(rect.X, rect.Y + radius), new NGraphics.ArcTo(new NGraphics.Size(radius, radius), true, false, new NGraphics.Point(rect.X + radius, rect.Y)),
new NGraphics.ClosePath()
};
}
public static string DrawCartIcon(int count, string path, double iconSize = 30, double scale = 2, string fontName = "Arial", double fontSize = 12, double textSpacing = 4)
{
var service = DependencyService.Get<IService>();
var canvas = service.GetCanvas();
if (_svgGraphic == null) using (var stream = typeof(CartIconHelper).GetTypeInfo().Assembly.GetManifestResourceStream(path))
_svgGraphic = new SvgReader(new StreamReader(stream)).Graphic;
//st = ReadFully(stream);
var minSvgScale = Math.Min(canvas.Size.Width / _svgGraphic.Size.Width, canvas.Size.Height / _svgGraphic.Size.Height) / 1.15;
var w = _svgGraphic.Size.Width / minSvgScale;
var h = _svgGraphic.Size.Height / minSvgScale;
_svgGraphic.ViewBox = new NGraphics.Rect(0, -14, w, h);
_svgGraphic.Draw(canvas);
if (count > 0)
{
var text = count > 99 ? "99+" : count.ToString();
var font = new NGraphics.Font(fontName, fontSize);
var textSize = canvas.MeasureText(text, font);
var textRect = new NGraphics.Rect(canvas.Size.Width - textSize.Width - textSpacing, textSpacing, textSize.Width, textSize.Height);
if (count < 10)
{
var side = Math.Max(textSize.Width, textSize.Height);
var elipseRect = new NGraphics.Rect(canvas.Size.Width - side - 2 * textSpacing, 0, side + 2 * textSpacing, side + 2 * textSpacing);
canvas.FillEllipse(elipseRect, NGraphics.Colors.Red);
textRect -= new NGraphics.Point(side - textSize.Width, side - textSize.Height) / 2.0;
}
else
{
var elipseRect = new NGraphics.Rect(textRect.Left - textSpacing, textRect.Top - textSpacing, textRect.Width + 2 * textSpacing, textSize.Height + 2 * textSpacing);
canvas.FillPath(RoundRect(elipseRect, 6), NGraphics.Colors.Red);
}
var testReact1= new NGraphics.Rect(20,12,0,0);
// canvas.DrawText(text, textRect + new NGraphics.Point(0, textSize.Height), font, NGraphics.TextAlignment.Center, NGraphics.Colors.Black);
canvas.DrawText("5", testReact1, font, NGraphics.TextAlignment.Left, NGraphics.Colors.White);
}
service.SaveImage(canvas.GetImage());
string imagePath = service.GetImage();
return imagePath;
// return st;
}
}
Step 2: Create a interface to IService in PCL
public interface IService
{
IImageCanvas GetCanvas();
void SaveImage(NGraphics.IImage image);
string GetImage();
}
Step 3 : Implement this interface in your Android project
class CanvasServices:IService
{
private readonly AndroidPlatform _platform;
public CanvasServices()
{
_platform = new AndroidPlatform();
}
public void SaveImage(IImage image)
{
var dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(dir, "cart.png");
var stream = new FileStream(filePath, FileMode.Create);
image.SaveAsPng(stream);
//bitmap.Compress(image., 100, stream);
stream.Close();
}
public string GetImage()
{
var dir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var filePath = System.IO.Path.Combine(dir, "cart.png");
using (var streamReader = new StreamReader(filePath))
{
string content = streamReader.ReadToEnd();
System.Diagnostics.Debug.WriteLine(content);
}
return filePath;
}
public IImageCanvas GetCanvas()
{
NGraphics.Size size = new NGraphics.Size(30);
return _platform.CreateImageCanvas(size);
}
public NGraphics.AndroidPlatform GetPlatform()
{
return _platform;
}
}
Setp 4: Now, use CartIcon Helper in your PCL project to show badges in TabBarItem.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var imagePath = CartIconHelper.DrawCartIcon(2, "ToolBarAndroidBadge.Resources.cartIcon.svg");
string deviceSepecificFolderPath = Device.OnPlatform(null, imagePath, null);
object convertedObject = new FileImageSourceConverter().ConvertFromInvariantString(deviceSepecificFolderPath);
FileImageSource fileImageSource = (FileImageSource)convertedObject;
ToolbarItem cartItem = new ToolbarItem();
cartItem.Text = "My Cart";
cartItem.Order = ToolbarItemOrder.Primary;
cartItem.Icon = fileImageSource;
ToolbarItems.Add(cartItem);
}
}
For any one who wants to add badge on toolbar item using custom ui try,
Instead of using default toolbar item, you can hide the default navigation bar by NavigationPage.SetHasNavigationBar(this, false);
in the constructor.
Then prepare the custom navigation bar with toolbar item with badge as mentioned in above answers.
If you are using master detail page, hiding default navigation bar will hide hamburger icon, so need to slide from left to see sliding menu. Alternate method would be place a button with hamburger icon in custom navigation bar, on button click use messaging center to present the sliding menu.
Example: On page in which hamburger button is clicked
private void Button_Clicked(object sender, System.EventArgs e)
{
MessagingCenter.Send(this, "presnt");
}
On MasterDetail page
MessagingCenter.Subscribe<YourPage>(this, "presnt", (sender) =>
{
IsPresented = true;
});
Before making IsPresented=true, check for sliding menu is not all-ready presented.
Check https://github.com/LeslieCorrea/Xamarin-Forms-Shopping-Cart for badge on toolbar item.
Implement below code to draw a ground circle with text over toolbar icon
BarButtonItemExtensions.cs
using CoreAnimation;
using CoreGraphics;
using Foundation;
using ObjCRuntime;
using System;
using System.Linq;
using System.Runtime.InteropServices;
using UIKit;
namespace TeamCollaXform.Views.Services
{
public static class BarButtonItemExtensions
{
enum AssociationPolicy
{
ASSIGN = 0,
RETAIN_NONATOMIC = 1,
COPY_NONATOMIC = 3,
RETAIN = 01401,
COPY = 01403,
}
static NSString BadgeKey = new NSString(#"BadgeKey");
[DllImport(Constants.ObjectiveCLibrary)]
static extern void objc_setAssociatedObject(IntPtr obj, IntPtr key, IntPtr value, AssociationPolicy policy);
[DllImport(Constants.ObjectiveCLibrary)]
static extern IntPtr objc_getAssociatedObject(IntPtr obj, IntPtr key);
static CAShapeLayer GetBadgeLayer(UIBarButtonItem barButtonItem)
{
var handle = objc_getAssociatedObject(barButtonItem.Handle, BadgeKey.Handle);
if (handle != IntPtr.Zero)
{
var value = ObjCRuntime.Runtime.GetNSObject(handle);
if (value != null)
return value as CAShapeLayer;
else
return null;
}
return null;
}
static void DrawRoundedRect(CAShapeLayer layer, CGRect rect, float radius, UIColor color, bool filled)
{
layer.FillColor = filled ? color.CGColor : UIColor.White.CGColor;
layer.StrokeColor = color.CGColor;
layer.Path = UIBezierPath.FromRoundedRect(rect, radius).CGPath;
}
public static void AddBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor, bool filled = true, float fontSize = 11.0f)
{
if (string.IsNullOrEmpty(text))
{
return;
}
CGPoint offset = CGPoint.Empty;
if (backgroundColor == null)
backgroundColor = UIColor.Red;
var font = UIFont.SystemFontOfSize(fontSize);
if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
{
font = UIFont.MonospacedDigitSystemFontOfSize(fontSize, UIFontWeight.Regular);
}
var view = barButtonItem.ValueForKey(new NSString(#"view")) as UIView;
var bLayer = GetBadgeLayer(barButtonItem);
bLayer?.RemoveFromSuperLayer();
var badgeSize = text.StringSize(font);
var height = badgeSize.Height;
var width = badgeSize.Width + 5; /* padding */
//make sure we have at least a circle
if (width < height)
{
width = height;
}
//x position is offset from right-hand side
var x = view.Frame.Width - width + offset.X;
var badgeFrame = new CGRect(new CGPoint(x: x - 4, y: offset.Y + 5), size: new CGSize(width: width, height: height));
bLayer = new CAShapeLayer();
DrawRoundedRect(bLayer, badgeFrame, 7.0f, backgroundColor, filled);
view.Layer.AddSublayer(bLayer);
// Initialiaze Badge's label
var label = new CATextLayer();
label.String = text;
label.TextAlignmentMode = CATextLayerAlignmentMode.Center;
label.SetFont(CGFont.CreateWithFontName(font.Name));
label.FontSize = font.PointSize;
label.Frame = badgeFrame;
label.ForegroundColor = filled ? textColor.CGColor : UIColor.White.CGColor;
label.BackgroundColor = UIColor.Clear.CGColor;
label.ContentsScale = UIScreen.MainScreen.Scale;
bLayer.AddSublayer(label);
// Save Badge as UIBarButtonItem property
objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, bLayer.Handle, AssociationPolicy.RETAIN_NONATOMIC);
}
public static void UpdateBadge(this UIBarButtonItem barButtonItem, string text, UIColor backgroundColor, UIColor textColor)
{
var bLayer = GetBadgeLayer(barButtonItem);
if (string.IsNullOrEmpty(text) || text == "0")
{
bLayer?.RemoveFromSuperLayer();
objc_setAssociatedObject(barButtonItem.Handle, BadgeKey.Handle, new CAShapeLayer().Handle, AssociationPolicy.ASSIGN);
return;
}
var textLayer = bLayer?.Sublayers?.First(p => p is CATextLayer) as CATextLayer;
if (textLayer != null)
{
textLayer.String = text;
}
else
{
barButtonItem.AddBadge(text, backgroundColor, textColor);
}
}
}
}
ToolbarItemBadgeService.cs
using TeamCollaXform.Views.Services;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: Dependency(typeof(ToolbarItemBadgeService))]
namespace TeamCollaXform.Views.Services
{
/// <summary>
///
/// </summary>
public interface IToolbarItemBadgeService
{
void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor);
}
/// <summary>
///
/// </summary>
public class ToolbarItemBadgeService : IToolbarItemBadgeService
{
public void SetBadge(Page page, ToolbarItem item, string value, Color backgroundColor, Color textColor)
{
Device.BeginInvokeOnMainThread(() =>
{
var renderer = Platform.GetRenderer(page);
if (renderer == null)
{
renderer = Platform.CreateRenderer(page);
Platform.SetRenderer(page, renderer);
}
var vc = renderer.ViewController;
var rightButtomItems = vc?.ParentViewController?.NavigationItem?.RightBarButtonItems;
var idx = rightButtomItems.Length - page.ToolbarItems.IndexOf(item) - 1; //Revert
if (rightButtomItems != null && rightButtomItems.Length > idx)
{
var barItem = rightButtomItems[idx];
if (barItem != null)
{
barItem.UpdateBadge(value, backgroundColor.ToUIColor(), textColor.ToUIColor());
}
}
});
}
}
}
Usage
void OnAttachClicked(object sender, EventArgs e)
{
//var answer = await DisplayAlert("Question?", "Would you like to play a game", "Yes", "No");
//Debug.WriteLine("Answer: " + answer);
ToolbarItem cmdItem = sender as ToolbarItem;
DependencyService.Get<IToolbarItemBadgeService>().SetBadge(this, cmdItem, $"2", Color.DarkOrange, Color.White);
}
Links: 1) for instruction and 2) for sample code
https://www.xamboy.com/2018/03/08/adding-badge-to-toolbaritem-in-xamarin-forms/
https://github.com/CrossGeeks/ToolbarItemBadgeSample

Scrolling with mouse Win 8.1 Metro Hub Navigation

I am trying to find a solution to allow a Hub to pan with the mouse when its reaches the left or right boundary. I have implemented the code below which i have gleaned from various sources.
` private void theHubPointerMoved(object sender, PointerRoutedEventArgs e)
{ Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(null);
if (ptrPt.Position.X < this.ActualWidth - 20)
if (ptrPt.Position.X > 20)
{
//Do the SCROLLING HERE
var xcord = Math.Round(ptrPt.Position.X, 2);
var ycord = Math.Round(ptrPt.Position.Y, 2);
}
}
e.Handled = true;
}`
So it is relativley easy to see when the mouse is at the screen edge. I thought it would be easy to simply use the MyHub.ScrollViewer.ScrollToHorizontalOffset(xcord); but the Hub Scrollviewer doesnt expose this ScrollToHorizontalOffset function.
Can anyone assist?
Thanks.
Oh, it's exposed. If you can handle digging for it. Here's how:
http://xaml.codeplex.com/SourceControl/latest#Blog/201401-ScrollHub/MainPage.xaml.cs
In the example below, it is scrolling to a specific hub section. But you should be able to easily adapt it to your specific needs, I hope.
private void ScollHubToSection(Hub hub, HubSection section)
{
var visual = section.TransformToVisual(this.MyHub);
var point = visual.TransformPoint(new Point(0, 0));
var viewer = Helpers.FindChild<ScrollViewer>(hub, "ScrollViewer");
viewer.ChangeView(point.X, null, null);
}
Using this:
public class Helpers
{
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
T childType = child as T;
if (childType == null)
{
foundChild = FindChild<T>(child, childName);
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
if (frameworkElement != null && frameworkElement.Name == childName)
{
foundChild = (T)child;
break;
}
}
else
{
foundChild = (T)child;
break;
}
}
return foundChild;
}
}
Best of luck!

How to scroll axis scale outside the graph of Zedgraph using the mouse event

Is it possible that the axis scale outside the graph could be scale using the mouse event "mouse_down and hold" and move up or down in y-axis the same with the x-axis move left or right? ex. when I trigger MouseDownEvent and hold the x-axis scale 0.6 or at the space along with that scale and move it to the right, scale should scroll depend in the chartfraction? could you post an example? Thanks in advance!
Separately panning and zooming Y axises can be achieved using the mouse events of ZedGraph: MouseDownEvent, MouseMoveEvent, MouseUpEvent and MouseWheel events (credits go to a colleague of mine).
It works with multiple GraphPanes and multiple Y axises.
The MouseMoveEvent is used to shift the Min and the Max of an Y axis when the mouse is moved while its button is pressed. If not, it is used to get the reference of the Y axis object the mouse is hovering on.
The MouseDownEvent is used to initiate an axis pan operation.
The MouseWheel is used to perform a zoom on an Y axis.
And the MouseUpEvent is used to clean things when zooming and panning operations are finished.
Here is the code :
// The axis that is currently hovered by the mouse
YAxis hoveredYAxis;
// The graphpane that contains the axis
GraphPane foundPane;
// The scale of the axis before it is panned
double movedYAxisMin;
double movedYAxisMax;
// The Y on the axis when the panning operation is starting
float movedYAxisStartY;
void z_MouseWheel(object sender, MouseEventArgs e)
{
if (hoveredYAxis != null)
{
var direction = e.Delta < 1 ? -.05f : .05f;
var increment = direction * (hoveredYAxis.Scale.Max - hoveredYAxis.Scale.Min);
var newMin = hoveredYAxis.Scale.Min + increment;
var newMax = hoveredYAxis.Scale.Max - increment;
hoveredYAxis.Scale.Min = newMin;
hoveredYAxis.Scale.Max = newMax;
foundPane.AxisChange();
z.Invalidate();
}
}
bool z_MouseUpEvent(ZedGraphControl sender, MouseEventArgs e)
{
hoveredYAxis = null;
return false;
}
bool z_MouseMoveEvent(ZedGraphControl sender, MouseEventArgs e)
{
var pt = e.Location;
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (hoveredYAxis != null)
{
var yOffset = hoveredYAxis.Scale.ReverseTransform(pt.Y) - hoveredYAxis.Scale.ReverseTransform(movedYAxisStartY);
hoveredYAxis.Scale.Min = movedYAxisMin - yOffset;
hoveredYAxis.Scale.Max = movedYAxisMax - yOffset;
sender.Invalidate();
return true;
}
}
else
{
var foundObject = findZedGraphObject(null);
hoveredYAxis = foundObject as YAxis;
if (hoveredYAxis != null)
{
z.Cursor = Cursors.SizeNS;
return true;
}
else
{
if (z.IsShowPointValues)
{
z.Cursor = Cursors.Cross;
return false;
}
else
{
z.Cursor = Cursors.Default;
return true;
}
}
}
return false;
}
bool z_MouseDownEvent(ZedGraphControl sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
if (hoveredYAxis != null)
{
movedYAxisStartY = e.Location.Y;
movedYAxisMin = hoveredYAxis.Scale.Min;
movedYAxisMax = hoveredYAxis.Scale.Max;
return true;
}
}
return false;
}
This is a helper that factorizes a bit the object find operations of ZedGraph.
object findZedGraphObject(GraphPane pane = null)
{
var pt = zgc.PointToClient(Control.MousePosition);
if (pane == null)
{
foundPane = zgc.MasterPane.FindPane(pt);
if (foundPane != null)
{
object foundObject;
int forget;
using (var g = zgc.CreateGraphics())
if (foundPane.FindNearestObject(pt, g, out foundObject, out forget))
return foundObject;
}
}
return null;
}
If I understand your question correctly, here's my response:
zedgraph has got an in-built function called "Pan", you could change the scale of x & y axis.
Place the cursor within the 'chart area'
Hold the 'ctrl' button & move the mouse towards x & y directions to change the scale.
you could get back to original state by 'Un-Pan' (Context Menu)
Cheers..:)
Do You want to create a ScrollBar?
zedGraphControl1.IsShowHScrollbar = true;
//Set borders for the scale
zedGraphControl1.GraphPane.XAxis.Scale.Max = Xmax;
zedGraphControl1.GraphPane.XAxis.Scale.Min = Xmin;

android expandableListView animate slide up?

I want to animate slide down and slide up on expandablelistview when I click the groupItem.Then I have finish the slide down.
public class ExpandAnimation extends Animation {
private static final String TAG = "ExpandAnimation";
private View mAnimatedView;
private LayoutParams mViewLayoutParams;
private int mMarginStart, mMarginEnd;
private boolean mIsVisibleAfter = false;
private boolean mWasEndedAlready = false;
/**
* Initialize the animation
* #param view The layout we want to animate
* #param duration The duration of the animation, in ms
*/
public ExpandAnimation(View view, int duration) {
setDuration(duration);
mAnimatedView = view;
mViewLayoutParams = (LayoutParams) view.getLayoutParams();
// if the bottom margin is 0,
// then after the animation will end it'll be negative, and invisible.
mIsVisibleAfter = (mViewLayoutParams.bottomMargin == 0);
mMarginStart = mViewLayoutParams.bottomMargin;
Log.i(TAG, "mMarginStart:>>>>>>>"+mMarginStart);
mMarginEnd = (mMarginStart == 0 ? (0- view.getHeight()) : 0);
Log.i(TAG, "mMarginEnd:>>>>>>>"+mMarginEnd);
view.setVisibility(View.VISIBLE);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
Log.i(TAG, "applyTransformation-->"+interpolatedTime);
if (interpolatedTime < 1.0f) {
// Calculating the new bottom margin, and setting it
mViewLayoutParams.bottomMargin = mMarginStart
+ (int) ((mMarginEnd - mMarginStart) * interpolatedTime);
// Invalidating the layout, making us seeing the changes we made
mAnimatedView.requestLayout();
// Making sure we didn't run the ending before (it happens!)
} else if (!mWasEndedAlready) {
mViewLayoutParams.bottomMargin = mMarginEnd;
mAnimatedView.requestLayout();
if (mIsVisibleAfter) {
mAnimatedView.setVisibility(View.GONE);
}
mWasEndedAlready = true;
}
}
}
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
Log.i(TAG, "getChildView");
#SuppressWarnings("unchecked")
String text = ((Map<String, String>) getChild(groupPosition,
childPosition)).get("child");
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.child, null);
}
View toolbar = convertView.findViewById(R.id.toolbar);
setAnimationView(toolbar);
((LinearLayout.LayoutParams) toolbar.getLayoutParams()).bottomMargin = -75;
toolbar.setVisibility(View.GONE);
ExpandAnimation expandAni = new ExpandAnimation(toolbar, 1000);
toolbar.startAnimation(expandAni);
TextView tv = (TextView) convertView.findViewById(R.id.childTo);
tv.setText(text);
return convertView;
}
But when I click the groupItem to collapse the group,it doesn't call the getChildView() method.So how can I to call the getChildView() and let it slide up?
I believe that you want to extend BaseExpandableListAdapter if you want to call (or #Override) getChildView.
http://developer.android.com/reference/android/widget/BaseExpandableListAdapter.html