Reset view after UIRotationGesture - xamarin.ios

I have a UIRotationRecognizer on an UIImageView. After I rotate the view I would like to commit the changes so that next time I rotate the image it rotates naturally. Currently, with the code below, it looks like the origin is off after release the touch and try to rotate again.
[Export("RotationSelector")]
private void RotationSelector(UIRotationGestureRecognizer recognizer)
{
recognizer.View.Transform = CGAffineTransform.MakeRotation(recognizer.Rotation);
if (recognizer.State == UIGestureRecognizerState.Ended)
// Reset origin here...
}
Thanks

You need to reset your transformation like this:
recognizer.View.Transform = CGAffineTransform.MakeIdentity();

Related

SwiftUI ColorPicker "opened" and "closed" events?

I need to be able to undo / redo the colors that are picked with the new SwiftUI ColorPicker ( on the iPad : it's presented as a floating window )
The thing that makes it very difficult is that there is apparently no way to know that the user has indeed chosen a color ( and therefore closed the panel )
Instead, the behavior of ColorPicker is that it will keep updating the binded color as the user is manipulating the color controls. This is very helpful to show a live preview, but you don't want to register all these color variations for undo / redo purposes : you only want the color that was finally picked.
Therefore there is no logical distinction between the colors that the user tried, and the one that was selected
And I looked everywhere : there aren't any modifiers / notifications related to that.
I know SwiftUI hasn't been there for long, but this seems like a crucial functionality that's missing?
Has anyone found a workaround?
Undo is always tricky. One size does not fit all. In this case a good solution is to throttle the number of events that come into the UndoManager. You can do so by comparing the current time to the time you last commit.
Create a view model that represents your Source of Truth, and conform to ObservableObject to publish events. It will own the UndoManager. It will have a computed property that gets/sets to the internal data, and check the current time against the time of last commit.
class EditViewModel: ObservableObject {
var commitTime = Date.now
let undoManager = UndoManager()
private var _color: Color = .red {
didSet {
objectWillChange.send()
}
}
var color: Color {
get { _color }
set {
let oldValue = color
let now = Date.now
if now.timeIntervalSince(commitTime) > 1 {
undoManager.registerUndo(withTarget: self) {
$0.color = oldValue
}
}
self.commitTime = now
_color = newValue
}
}
}
Now all that's left to do is create your view and pass in the binding. The implementation details are opaque to the View since it is managed by the ViewModel.
struct EditView: View {
#StateObject var vm = EditViewModel()
var body: some View {
Form {
ColorPicker("Color", selection: $vm.color)
}
}
}
If you need even more control, you can additionally compare the last committed color to the new value and only commit if there is a significant change.
I will also agree that a data-driven approach like SwiftUI's can make undo more tricky. For example, when you need to coalesce multiple operations together into one undo group. By its very nature an undo group is procedural-- the user did one thing after the other, and finally terminates on some condition. But I'm sure there is some way to encapsulate this step-wise operation in a transaction object of some kind.
Undo is hard!

JAVAFX imageview allow user to add tag

I am making an image gallery using javafx, i wish to have the feature which allow the user to add some tag(for human faces) to the imageview when the user is onclick at the imageview, it should grab the position of the mouse pointed and prompt a dialog for user to enter the name for the face and save it to database.
Is this achievable by using javafx?
If yes, how should i do that?
Your help is appreciated.
Sample output of my application below:
Sure it's possible. I created this simple example for a single Image that adds a button to the scene which adds a circle where the image was clicked. This should demonstrate the approach.
#Override
public void start(Stage primaryStage) {
ImageView imageView = new ImageView(...);
imageView.setPreserveRatio(true);
imageView.setFitHeight(200);
StackPane pane = new StackPane();
StackPane.setAlignment(imageView, Pos.TOP_LEFT);
pane.getChildren().add(imageView);
VBox box = new VBox(pane);
pane.setOnMouseClicked(evt -> {
if (evt.getButton() == MouseButton.PRIMARY) {
// create node(s) that uses the click data
Button button = new Button("Show point");
button.setOnAction(e -> {
// do something with the data on user interaction
box.getChildren().remove(button);
Circle circle = new Circle(evt.getX(), evt.getY(), 5, Color.RED);
Pane circlePane = new Pane(circle);
StackPane.setAlignment(circlePane, Pos.TOP_LEFT);
pane.getChildren().add(circlePane);
});
box.getChildren().add(button);
}
});
Scene scene = new Scene(box, 200, 300);
primaryStage.setScene(scene);
primaryStage.show();
}
For your application you would:
Create a different event handler that creates and/or initializes the UI according to your needs or shows a dialog. You also would register the listener to the ImageView directly (unless you need to add some elements on top of it, like I do)
Calculate the real click position in image coordinates using evt.getX() * imageView.getImage().getWidth() / imageView.getLayoutBounds().getWidth() (absolute position) or evt.getX() / imageView.getLayoutBounds().getWidth() (relative position); procede accordingly for y position. Do this calculation directly in the click handler, not when the user submits the entered information, since you may want the user to be able to resize the image. Also if you use the viewport property, you need to modify the calculations accordingly.
Create a different thread that sends the information to the database, when the user submits his/her edits. Of course you also need to store some information about the image currently shown in the ImageView somewhere.

How to listen to android googlemaps geofence transitions

How can i make something happen when my location on a map enters and exits one of my application google map's fence. I cant seem to understand the tutorial of google regarding geofencing. And i cant find any other tutorial of this thing.
this are my code..
#Override
protected void onCreate(Bundle savedInstanceState) {
...
buildGeofence(14.728801, 120.961209, "Id_test", 500);
}
private void buildGeofence(double latitude ,double longitude, String requestId, int radius){
int GEOFENCE_TRANSITION_ENTER = 1;
LatLng geofencePoint = new LatLng(latitude, longitude);
//int radius = 500;
Geofence.Builder geofence = new Geofence.Builder();
geofence.setCircularRegion(geofencePoint.latitude,geofencePoint.longitude, radius);
geofence.setRequestId(requestId);
geofence.setExpirationDuration(Geofence.NEVER_EXPIRE);
geofence.setTransitionTypes(GEOFENCE_TRANSITION_ENTER);
geofence.setNotificationResponsiveness(0);
geofence.build();
CircleOptions circleOptions = new CircleOptions();
circleOptions.center(geofencePoint);
circleOptions.radius(radius);
circleOptions.strokeColor(Color.BLACK);
circleOptions.strokeWidth(2);
circleOptions.fillColor(0x30ff0000);
mMap.addCircle(circleOptions);
}
Dens,
To make something happen when you transition the Geofence you need to
Create an intent for Geofence transitions.
Create a GeofencingRequest.
Add the intent, GeofenceingRequest, and GoogleApiClient to the LocationServices.GeofencingApi API.
Handle the intent.
The code you have written so far will create a geofence and a circle on the map, but it will not yet do anything when the fence is transitioned.
In the tutorial you linked, you successfully created a geofence, but now you need to follow some of the other steps. Make sure you follow the steps in "Specify geofences and initial triggers", "Define an Intent for geofence transitions", and "Add geofences". This should complete steps 1, 2, and 3 that I listed above. One you have those steps working, try the section "Handle Geofence Transitions", which will complete step 4 that I listed above.
I hope this helps you!
P.S.: Since I see you are adding circles to the map, you may quickly discover you need a way to keep track of these circles in order to correctly add and remove them for each geofence. There is a short blog post here that discusses how to do this.

Highlighting or Bolding the Borders of a kml Polygon

Hey after loading a kml file to google earth I was trying to have when a user clicks a certain polygon from the kml, to have that polygon highlighted.
So far I can record the click event, get the event type (KmlPlacemark) and grab its kml markup.
I tried doing something similar to this example where they add a placemark to the getFeatures of the kmlObject but both target and type don't seem to have 'getFeatures'. After looking around the documentation I think I might either want setOutline from Kml Polystyle class or setWidth() from KmlLineStyle class but am not sure. Also when I try something like target.setOutline(true); it doesn't work.
Can anyone tell me if I'm on the right track, hints to what I'm doing wrong, and if there's a better way to do this?
function recordEvent(event) {
var target = event.getTarget();
var type = target.getType();
if(type == "KmlPolygon") {
alert("KMLPolygon ");
}else if(type == "KmlPlacemark") {
// // get the data you want from the target.
var description = target.getDescription();
var balloon = target.getBalloonHtml();
var outputKml = target.getKml();
if ('getFeatures' in event) {
console.log("test");
event.getFeatures().appendChild(placemark);
}
console.log("hello?")
// target.setOutline(true);
console.log(outputKml);
}
};
google.earth.addEventListener(ge.getGlobe(), 'click', recordEvent);
Thanks!
I find the best way to do what you are asking is to:
Detect click events like you currently do
If clicked, create a new Style, then assign it to the target
var newStyle = ge.createStyle('');
// Assign your Style's attributes such as LabelStyle and IconStyle
// eg to set the scale of your label
newStyle.getLabelStyle().setScale(2.5);
// Set the Style
target.setStyleSelector(newStyle);
Edit to add in this link of a Google example showing it more in depth
https://code.google.com/apis/ajax/playground/#styling_placemarks_using_style_maps

Nivo Slider - Hide thumbnails if there is only one image and prevent slideshow transitions

I am using the Nivo Slider for the first time and it is absolutely awesome however I do have a couple of issues.
I have it integrated within a CMS and this allows the user to add up to 5 images.
If there is only one image however, I would like to just hide the thumbnails and stop any transitions, as in sliding the same image in again and again.
Now is this something I would do with JQuery or should I be editing the 'jquery.nivo.slider.js' file? Or is it potentially something I could potentially accomplis in both?
I guess I am looking to do something like:
if images < 1 {
transition = false;
thumbnails = hide;
}
Hopefully that makes sense.
Thanks for your time and help.
UPDATE
Okay so I have managed to hide the thumbnails if there is only one image by adding the following to the jquery.nivo.slider.js file:
if (vars.totalSlides < 2)
{
$('.nivo-controlNav').remove();
}
I now want to be able to change one of the settings in the following piece of code based on the same rule but am not sure how to do this:
$.fn.nivoSlider.defaults = {
pauseOnHover: 'false',
......
}
I would change the config array and initialize the slider like this:
// nivo config array
var nivoConfig = {
slices: 30, // For slice animations
boxCols: 16, // For box animations
// put all your init config here but exclude 'effects'
}
if(imagesCount < 2) {
nivoConfig['effects'] = 'none';
} else {
nivoConfig['effects'] = 'random';
}
$('#slider').nivoSlider(nivoConfig);
Try it out, it should work in a way like this.
I had this exact same problem; Johnny's code worked perfectly, but I wanted to elaborate for people who may be having problems with this. You'll want to insert:
if (vars.totalSlides < 2) {
$('.nivo-controlNav').remove();
}
on or around line 158 in the jquery.nivo.slider.js file (within the if(settings.controlNav) {} conditional). Otherwise it won't work.

Resources