Switch to another View, but stay in the Navigation Controller - uiviewcontroller

I have a navigation controller with details about a specific product, one of the details is a small image of the product. Now I want to add a button which must go to a view controller with a enlarged image of the product.
How can I make that the enlarged image is on the same navigation controller as the detail screen and as transition an flip of the screen but that the header and tab bar won't flip.
Added a overview image of the two views on the navigation controller.

You can use something like:
UIView.Transition(this.NavigationController.View, 1f,
UIViewAnimationOptions.CurveEaseInOut | UIViewAnimationOptions.TransitionFlipFromRight,
delegate { this.NavigationController.PushViewController(this.ImageViewController, false); });
To have your image view flipped in when getting pushed on the navogation controller, instead of the default transition. The title property of the ImageViewController should be the same as the one from your details.
The idea of the UINavigationController is to handle multiple controllers, so you should not work against it by overlaying a view.

Add two views to the controller and animate their frame properties to get the effect you want.
See the example below.
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;
namespace delete20121203
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
// class-level declarations
UIWindow window;
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
var ctrl = new MyViewController ();
var nav = new UINavigationController (ctrl);
window.RootViewController = nav;
// make the window visible
window.MakeKeyAndVisible ();
return true;
}
}
public class MyViewController : UIViewController
{
UIButton _button1;
UIButton _button2;
UIView _view1;
UIView _view2;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
Title = "Test";
_view1 = new UIView (View.Bounds);
_view1.AutoresizingMask = UIViewAutoresizing.All;
_view1.BackgroundColor = UIColor.White;
_button1 = UIButton.FromType (UIButtonType.RoundedRect);
_button1.Frame = new System.Drawing.RectangleF (10, 10, 150, 44);
_button1.SetTitle ("Click", UIControlState.Normal);
_button1.TouchUpInside += Button1Click;
_view2 = new UIView (View.Bounds);
_view2.AutoresizingMask = UIViewAutoresizing.All;
_view2.BackgroundColor = UIColor.LightGray;
RectangleF hideRect = _view2.Frame;
hideRect.X = hideRect.X + hideRect.Width;
_view2.Frame = hideRect;
_button2 = UIButton.FromType (UIButtonType.RoundedRect);
_button2.Frame = new System.Drawing.RectangleF (10, 10, 150, 44);
_button2.SetTitle ("Back", UIControlState.Normal);
_button2.TouchUpInside += Button2Click;
_view1.Add (_button1);
_view2.Add (_button2);
View.Add (_view1);
View.Add (_view2);
}
void Button1Click (object sender, EventArgs e)
{
UIView.Animate (.5f, 0, UIViewAnimationOptions.CurveEaseInOut, delegate {
_view2.Frame = View.Frame;
RectangleF hideRect = _view1.Frame;
hideRect.X = hideRect.X - hideRect.Width;
_view1.Frame = hideRect;
},
null);
}
void Button2Click (object sender, EventArgs e)
{
UIView.Animate (.5f, 0, UIViewAnimationOptions.CurveEaseInOut, delegate {
RectangleF hideRect = _view2.Frame;
hideRect.X = hideRect.X + hideRect.Width;
_view2.Frame = hideRect;
_view1.Frame = View.Frame;
},
null);
}
}
}

Related

TextureMapObject is not shown on isometric Tiled Map

In my code I'm using the following code to load the .tmx map. I also use IsometricTiledMapRenderer.
I would like to add a unit upon touch event on tile.
assetManager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
assetManager.load("maps/grass_and_water.tmx", TiledMap.class);
assetManager.finishLoading();
map = assetManager.get("maps/grass_and_water.tmx");
renderer = new IsometricTiledMapRenderer(map, 1f / 64f);
Gdx.input.setInputProcessor(new GestureDetector(new MapGestureListener(camera, jetFlyingSprite, map)));`
In the touchDown I'm trying to add TextureMapObject on click.
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
Gdx.app.log(TAG, "touchDown gesture");
flinging = false;
scale = camera.zoom;
//return false;
Vector3 clickCoordinates = new Vector3(x,y,0);
Vector3 position = camera.unproject(clickCoordinates);
Texture texture = new Texture("jet_flying.png");
TextureRegion textureRegion = new TextureRegion(texture,400,400);
MapLayer mapLayer = map.getLayers().get("objects");
mapLayer.setVisible(true);
TextureMapObject textureMapObject = new TextureMapObject(textureRegion);
textureMapObject.setName("plane");
textureMapObject.setX((float)position.x);
textureMapObject.setY((float)position.y);
mapLayer.getObjects().add(textureMapObject);
textureMapObject.setX((float)position.x);
textureMapObject.setY((float)position.y);
return true;
}
When running nothing happens when I click.
Any clues/?
I am guessing your "objects" layer is a Object layer, the implementation of that is left blank in BatchTiledMapRenderer which IsometricTiledMapRenderer inherits from. This means object layers are rendered.
BatchTiledMapRenderer renderMapLayer method which calls renderObject which looks like this:
#Override
public void renderObject (MapObject object) {
}
You could subclass IsometricTiledMapRenderer and implement renderObject yourself.

MvvmCross Tab navigation raises exception Trying to show a tab without a TabBarViewController, this is not possible

I'm trying to create tab navigation in iOS project using latest MvvmCross 5.x., but I'm getting the exception saying:
"Trying to show a tab without a TabBarViewController, this is not possible!"
Can anyone explain, what could be wrong, or is there any example simple project to show how tab navigation works using new latest MvvmCross 5.x version in iOS projects?
This is my code:
[Register("MainView")]
[MvxRootPresentation(WrapInNavigationController = true)]
public class MainView : MvxTabBarViewController<MainViewModel>
{
}
[MvxTabPresentation]
public partial class HomeView : MvxViewController<HomeViewModel>
{
}
public class IosViewPresenter : MvxIosViewPresenter
{
public override void Show(IMvxIosView view, MvxViewModelRequest request)
{
// This line gets called, but raises exception complaining that TabBarController is null.
base.Show(view, request);
}
}
[Register ("AppDelegate")]
public class AppDelegate : MvxApplicationDelegate
{
public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var setup = new Setup(this, Window);
setup.Initialize();
var start = Mvx.Resolve<IMvxAppStart>();
start.Start();
setup.EnsureInitialized(GetType());
Window.MakeKeyAndVisible();
return true;
}
}
public class Setup : MvxIosSetup
{
protected override IMvxIosViewPresenter CreatePresenter()
{
var viewModelLoader = new MvxViewModelLoader();
Mvx.RegisterSingleton<IMvxViewModelLoader>(() => viewModelLoader);
var presenter = new IosViewPresenter((MvxApplicationDelegate)ApplicationDelegate, Window, viewModelLoader);
Mvx.RegisterSingleton<IMvxIosViewPresenter>(presenter);
return presenter;
}
}

Cannot access the Navigation Bar in the second screen of the Navigation

I am developing an app using Xamarin.iOS. It will have a lot of screens that I cannot design using Main.StoryBoard, so I have to design every ViewController separately. Right now I have 2 screens: ViewController.cs and InProgress.cs. I have wrapt the ViewController.cs inside a NavigationController in Main.StoryBoard. Below is the code:
ViewController.cs (ViewDidLoad)
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//change the navigation bar controller
this.NavigationController.NavigationBar.BarTintColor = UIColor.FromRGB (26f / 255f, 56f / 255f, 100f / 255f);
this.NavigationController.NavigationBar.TitleTextAttributes = new UIStringAttributes()
{
ForegroundColor = UIColor.White
};
NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
//change the layout of collectionView Layout
//initialize the data
sectionCategories = new List<SectionCategory>();
sectionCategories.Add(new SectionCategory("Lajme", "http://www.ikub.al/media/iOS/lajme.jpg"));
......
sectionCategories.Add(new SectionCategory("Shtypi i dites", "http://www.ikub.al/media/HP/shtypi.jpg"));
sectionGrid.RegisterClassForCell(typeof(SectionViewCell), SectionViewCell.CellID);
sectionGrid.Source = new SectionViewSource (sectionCategories,this);
}
When I click an item of the sectionGrid it pushes a new ViewController in the stack.
var soonVC = new InProgress ("InProgress");
soonVC.Title = "InProgress";
owner.NavigationController.PushViewController(soonVC, true);
The InProgress screen has the a .cs file, a .desigener.cs file and .xib file like the following:
public partial class InProgress : UIViewController
{
String section;
public InProgress (String text) : base ("InProgress", null)
{
section = text;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning ()
{
base.DidReceiveMemoryWarning ();
// Release any cached data, images, etc that aren't in use.
}
}
[Register ("InProgress")]
partial class InProgress
{
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UILabel labelComingSoon { get; set; }
void ReleaseDesignerOutlets ()
{
if (labelComingSoon != null) {
labelComingSoon.Dispose ();
labelComingSoon = null;
}
}
}
But I have 2 problems:
I have to access the navigation bar of InProgress screen in order to change the back item, navigation style, text color, back button text, add new item etc.
When I have designed the layout in .xib file I have the label in the center, but in reality it's not in the center of the screen because it does not take into consideration the height of the navigation bar, so some layout may be hidden under the NavigationBar.
I have tried some piece of code like
soonVC.NavigationItem.LeftBarButtonItem.Title = " dsf";
but it gives me a null object.
Any suggestion for both the problems.
InProgress.xib
In your InProgress class you can set the back button text like so :
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
UIBarButtonItem newBackButton = new UIBarButtonItem("dfs",UIBarButtonItemStyle.Plain, (sender,args) => NavigationController.PopViewController (true));
NavigationItem.SetLeftBarButtonItem (newBackButton, false);
// The line below will move the search bar below the nav bar
NavigationController.NavigationBar.Translucent = false;
}
As for the next question:
When I have designed the layout in Xib file I have the label in the
center, but in reality its not in the center of the screen because it
does not take into consideration the height of the navigation bar, so
some layout may be hidden under the Navigation bar.
Are you using Autolayout? All you need to do is add a constraint to center vertical and it should center in the view. Are you able to upload your xib? if you are not using Autolayout you will just have to adjust for the Navigation Controller.
UPDATE
If you set your navbar to not be translucent it will go below the nav bar. You can set this in the InProgress class or when you here in the storyboard:
I have also added the autolayout constraints to your xib to center your label here is the xib xml:
HTH.

CustomMessageBox doesn't adapt when entering text

I've got a problem with a CustomMessageBox in Windows Phone. Normally when you got a page with several textboxes, then the view gets adapted/scrolled when a textinput starts.
But in a CustomMessageBox it seems no to work. It still adapts/scrolls the mainview, which is now in the background.
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var dialog = new CustomMessageBox()
{
Content = new FeedbackView(),
RightButtonContent = "Cancel",
LeftButtonContent = "Send",
VerticalContentAlignment = VerticalAlignment.Top,
VerticalAlignment = VerticalAlignment.Center,
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = HorizontalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
dialog.Show();
}
}
I made a little example: https://onedrive.live.com/redir?resid=6B27FD720F1FB58D!16324&authkey=!AKsq3XzgjQviN8w&ithint=folder%2csln
Does have anyone an idea to get this to work or do you think that I have to do this manually by myself?

Why JScrollPane does not react to mouse wheel events?

I have a JScrollPane containing a panel with a BoxLayout (PAGE AXIS).
My problem is that the JScrollPane does not react to mouse wheel events. To make it scroll using the mouse wheel i need to be on the JScrollBar.
I found this thread and i have no MouseMotionListener or MouseWheelListener, only a MouseListener. I think my problem come from the fact that my JScrollPane act on a JPanel that contains other panels itself. So when the mouse is on a panel within the JScrollPane it seems that the event is consumed by this panel i never seen by the scroll pane.
Is there a correct way to make the events caught by the children of the scroll pane visible to this scroll pane?
SSCCE:
Here a simple test case trying to show when i try to do in my Swing application.
The frame:
public class NewJFrame extends javax.swing.JFrame {
public NewJFrame() {
initComponents();
for (int i = 0; i < 50; i++) {
jPanel1.add(new TestPanel());
}
}
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.PAGE_AXIS));
jScrollPane1.setViewportView(jPanel1);
getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
pack();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new NewJFrame().setVisible(true);
}
});
}
}
And the TestPanel definition:
public class TestPanel extends javax.swing.JPanel {
public TestPanel() {
initComponents();
}
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
jLabel1.setText("jLabel1");
setBackground(new java.awt.Color(255, 51, 51));
setLayout(new java.awt.BorderLayout());
jLabel2.setText("TEST LABEL");
jLabel2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
add(jLabel2, java.awt.BorderLayout.PAGE_START);
jTextArea1.setEditable(false);
jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jTextArea1.setFocusable(false);
jScrollPane1.setViewportView(jTextArea1);
add(jScrollPane1, java.awt.BorderLayout.CENTER);
}
}
The JTextArea seems to consume the event since when the mouse cursor is inside it, the scrolling using wheel does not work. I have to put the mouse cursor outside the text area to make it works again.
Walter beat me to analysing the issue :-)
Adding a bit of detail:
It's correct that a JScrollPane supports mouseWheelHandling. According to the rules of mouseEvent dispatching, the top-most (in z-order) component gets the event, and that's the scrollPane around the textArea. So if wheeling the textarea is not required, a simple solution might be to disable the wheel-support in its scrollPane. And JScrollPane even has api for doing it:
scrollPane.setWheelScrollingEnabled(false);
Unfortunately, that doesn't work. Reason it's not working is that this property has no effect in the event dispatch chain which ultimately calls into eventTypeEnabled:
case MouseEvent.MOUSE_WHEEL:
if ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 ||
mouseWheelListener != null) {
return true;
}
This returns true if a mouseWheelListener is installed - which is done unconditionally by BasicScrollPaneUI, and not removed when the wheelEnabled property is changed (the ui doesn't even listen to that property ...) Plus the listener simply does nothing if the property is false. At least one of those facts is a bug, the ui should
either remove/add the listener depending on wheelEnabled
or: implement the listener such that it dispatches the event up the chain (as Walter does in his example)
The first option can be handled by application code:
scrollPane = new JScrollPane();
scrollPane.removeMouseWheelListener(scrollPane.getMouseWheelListeners()[0]);
it's a bit of a hack (as bug-workarounds always are :-), production code would have to listen to the wheelEnable to re-install if needed plus listen to LAF changes to update/re-remove the listeners installed by the ui.
Implementing the second option in slight modification (as to Walter's dispatching) by subclassing the JScrollPane and dispatch the event to parent if the wheelEnabled is false:
scrollPane = new JScrollPane() {
#Override
protected void processMouseWheelEvent(MouseWheelEvent e) {
if (!isWheelScrollingEnabled()) {
if (getParent() != null)
getParent().dispatchEvent(
SwingUtilities.convertMouseEvent(this, e, getParent()));
return;
}
super.processMouseWheelEvent(e);
}
};
scrollPane.setWheelScrollingEnabled(false);
The mouse wheel event gets consumed by the scroll pane around the text area. You can try to manually pass the event to the parent scroll pane like this:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestScrollPane2 {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
// might want to use a http://tips4java.wordpress.com/2009/12/20/scrollable-panel/
JPanel panel = new JPanel(new GridLayout(0, 1));
for (int i = 0; i < 10; i++) {
panel.add(new JScrollPane(new JTextArea(3, 40)) {
#Override
protected void processMouseWheelEvent(MouseWheelEvent e) {
Point oldPosition = getViewport().getViewPosition();
super.processMouseWheelEvent(e);
if(getViewport().getViewPosition().y == oldPosition.y) {
delegateToParent(e);
}
}
private void delegateToParent(MouseWheelEvent e) {
// even with scroll bar set to never the event doesn't reach the parent scroll frame
JScrollPane ancestor = (JScrollPane) SwingUtilities.getAncestorOfClass(
JScrollPane.class, this);
if (ancestor != null) {
MouseWheelEvent converted = null;
for (MouseWheelListener listener : ancestor
.getMouseWheelListeners()) {
listener.mouseWheelMoved(converted != null ? converted
: (converted = (MouseWheelEvent) SwingUtilities
.convertMouseEvent(this, e, ancestor)));
}
}
}
});
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(panel));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}