Cluster Marker Click Event Android - cluster-computing

I am using Google Maps Marker Clustering available in the utils library. On clicking a Cluster, the below onClusterClick method is not called. Is there a Cluster click event?
#Override
public boolean onClusterClick(Cluster<MyItem> cluster)
{
return true;
}

you need add this line before:
map.setOnMarkerClickListener(yourClusterManager);

Here is the way that how can achieve your requirement i.e. to click on cluster or cluster item.
mapSupportFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap; //(Here mMap is my GoogleMap object declared & was initialized).
// Initialize the manager with the context and the map.
mClusterManager = new ClusterManager<AppClusterItem>(MFragmentActivity.this, mMap);
mClusterManager.setRenderer(new MyCustomRender(MFragmentActivity.this, mMap, mClusterManager));
// Here which I used is my custom rendering class
// Point the map's listeners at the listeners implemented by the cluster manager.
mMap.setOnCameraChangeListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
mClusterManager.setOnClusterClickListener(new ClusterManager.OnClusterClickListener<AppClusterItem>() {
#Override
public boolean onClusterClick(Cluster<AppClusterItem> cluster) {
Log.e("I clicked # ", "Cluster which consumes whole list of ClusterItems");
return false;
}
});
mClusterManager.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<AppClusterItem>() {
#Override
public boolean onClusterItemClick(AppClusterItem item) {
Log.e("I clicked # ", "Cluster Item");
return false;
}
});
}
});
This solution will then not let you to use GoogleMap.setOnMarkerClickListener method, then so for it, you can read this answer.

maby its too late but if there any one want to know :
just set OnClusterItemClcikListener on your CkusterManger :
mClusterManager.setOnClusterItemClickListener(this);
then make you class implement ClusterManager.OnClusterItemClickListener
activity a implements ClusterManager.OnClusterItemClickListener ....
then finaly call
#Override
public boolean onClusterItemClick(ClusterItem clusterItem) {
Toast.makeText(getActivity(), "clciked", Toast.LENGTH_SHORT).show();
return true;
}

Related

Google Maps Android No Cluster/DeCluster on Zoom In/Out

I have implemented Google Maps Clustering on the iOS version of my app and it works fine. I am now attempting to implement Clustering on the Android version using the android maps utility library and it is not Declustering/Clustering when I zoom in or out.
Here is the cluster item class:
public class MyClusterItem implements ClusterItem {
private final LatLng position;
private final BitmapDescriptor icon;
private final String tag;
public MyClusterItem(double lat, double lng, BitmapDescriptor icon, String tag) {
this.position = new LatLng(lat, lng);
this.icon = icon;
this.tag = tag;
}
#Override
public LatLng getPosition() {
return position;
}
#Override
public String getTitle() {
return null;
}
#Override
public String getSnippet() {
return null;
}
public BitmapDescriptor getIcon() {
return icon;
}
public String getTag() {
return tag;
}
}
Here is how the cluster manager is implemented:
public void onMapReady(GoogleMap googleMap) {
//Log.i ( TAG, "Google Map Ready Callback" );
mMap = googleMap;
//mMap.setOnMarkerClickListener(this);
// Point the map's listeners at the listeners implemented by the cluster
// manager.
mMap.setOnCameraIdleListener(mClusterManager);
mMap.getUiSettings().setMapToolbarEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
mMap.getUiSettings().setRotateGesturesEnabled(false);
if (ActivityCompat.checkSelfPermission(MapsActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && isLocationEnabled) {
mMap.setMyLocationEnabled(true);
}
float mCurrentZoom = googleMap.getCameraPosition().zoom;
// Initialize the manager with the context and the map.
// (Activity extends context, so we can pass 'this' in the constructor.)
mClusterManager = new ClusterManager<MyClusterItem>(this, mMap);
mClusterManager.setOnClusterItemClickListener(mClusterItemClickListener);
mMap.setOnMarkerClickListener(mClusterManager);
mClusterManager.setOnClusterClickListener(new ClusterManager.OnClusterClickListener<MyClusterItem>() {
#Override
public boolean onClusterClick(final Cluster<MyClusterItem> cluster) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
cluster.getPosition(), (float) Math.floor(mMap
.getCameraPosition().zoom + 1)), 300,
null);
return true;
}
});
}
Cluster Items are added from a Firebase database as follows:
markerRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
try {
tableCount = tableCount+1;
markerKey = dataSnapshot.getKey();
markerData = dataSnapshot.getValue(Markers.class);
MyClusterItem markerItem = new PicNickClusterItem(markerData.y, markerData.x, BitmapDescriptorFactory.fromResource(R.drawable.verified), markerKey);
mClusterItemMap.put(markerKey, markerItem);
mClusterManager.addItem(markerItem);
if(tableCount >= numTables) {
//cluster markers
mClusterManager.cluster();
}
} catch (Error error) {
noFirebaseAccessAlert();
}
}
}
Screenshot of the initial map:
Screenshot when zoomed out:
Screenshot when zoomed in:
Cluster Items are not being clustered/declustered when zooming out/in and there is no animation. As I zoom out I would expect the cluster items to move into clusters and as I zoom in Cluster Items to separate from clusters as they do in the iOS version of the app. Also when I tap on a cluster marker, the map zooms in, but the cluster does not expand into cluster items. None of the cluster items have the same lat/lng and are separated by significant distances.
In the iOS version I was able to set the algorithm (non hierarchical distance based) & several "buckets" for clustering (and specify custom icons for each). I need to have both versions looks and respond the same so that the user has the same experience on both iOS and Android devices.

How to detect backspace in an Entry control when it is empty

I am using Xamarin.Forms with Android. I have a form which has 4 Entry controls for a user to enter code. I am using TextChanged event to detect user input and automatically move focus to the next control. This part works fine, i.e. as user types a digit focus automatically jumps to the next entry. However, I need to achieve the opposite, user should be able to tap backspace button and focus should move to the previous control. The problem is that TextChanged is not triggered when entry control is empty. How can I achieve this? Is there a custom renderer I can create for android to capture text input? Maybe there is a way to use 1 entry instead but I need to make it look like distinct 4 boxes.
Finally,I've found a solution for this by implementing a renderer in android.
In shared code(PCL),Create a class like this
public class CustomEntry:Entry
{
public delegate void BackspaceEventHandler(object sender, EventArgs e);
public event BackspaceEventHandler OnBackspace;
public CustomEntry()
{
}
public void OnBackspacePressed()
{
if (OnBackspace != null)
{
OnBackspace(null, null);
}
}
}
And,Then in your android project create a renderer like this:
public class CustomEntryRenderer: EntryRenderer
{
public override bool DispatchKeyEvent(KeyEvent e)
{
if (e.Action == KeyEventActions.Down)
{
if (e.KeyCode == Keycode.Del)
{
if (string.IsNullOrWhiteSpace(Control.Text))
{
var entry = (PasswordBox)Element;
entry.OnBackspacePressed();
}
}
}
return base.DispatchKeyEvent(e);
}
protected override void
OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
}
}
And then use it like this:
Entry1.OnBackspace += Entry1BackspaceEventHandler;
public void Entry1BackspaceEventHandler()
{
//things you want to do
}

Prevent selection of Tree Cell from right-click on Tree View Cell

I'm developing a custom TreeView object.
I'm using a custom cellFactory to provide the TreeCell objects of my TreeView.
This allows me to install custom Context Menu on the various cells, depending on the Item they are displaying.
But I'm not entirely satisfied with the behaviour.
When left-clicking on cell, it gets selected (OK)
But when right-clicking a cell, the context menu is displayed (OK) but the cell is also selected. (NOK)
How can I change this behaviour ?
I tried to implement an eventFilter on the tree view, to consume the event if it is a right-click but this doesn't change anything, the above behaviour still applies.
addEventFilter(MouseEvent.MOUSE_CLICKED,
new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
if (event.getButton() == MouseButton.SECONDARY) {
event.consume();
}
}
});
setCellFactory(new Callback<TreeView<TreeDisplayable>, TreeCell<TreeDisplayable>>() {
#Override
public TreeCell<TreeDisplayable> call(
final TreeView<TreeDisplayable> treeView) {
return new TreeDisplayableTreeCell(owner, javaModel);
}
});
public class TreeDisplayableTreeCell extends TreeCell<TreeDisplayable> {
...
#Override
public void updateItem(TreeDisplayable item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
setText(getItem().treeViewString());
setGraphic(item.getPic());
if (getTreeItem().getParent() == null) {
// it means it's the root node
setContextMenu(new RootItemContextMenu(javaModel, owner));
} else {
setContextMenu(new TreeItemContextMenu(javaModel, owner,getTreeItem().getValue()));
}
}
}
}
Reacting on Tony's comment
Creating a custom EventDispatcher does the trick.
public class TreeEventDispatcher implements EventDispatcher {
#Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
event.consume();
} else {
event = tail.dispatchEvent(event);
}
} else {
event = tail.dispatchEvent(event);
}
return event;
}
}
The behaviour is identical for all events, except the right click event, which is consumed, thus preventing the right-click selection of any TreeCell.
Luckily enough, the context menu is still displayed on right click (although I don't understand why ...) Does anybody have a clue ?
Previous Facewindu answer is actually working, but there is another way to achieve that behavior and still have context menu appearing on right click:
treeView.addEventFilter(MOUSE_PRESSED, event -> {
if (event.isSecondaryButtonDown()) {
Node text = (Node) event.getTarget();
TreeCell<...> treeCell = (TreeCell<...>) text.getParent();
treeCell.getContextMenu().show(treeCell, 0, 0);
event.consume();
}
});

How to use events in GWT Frame

I would like to capture all events within a GWT frame. I've found several ways to do this, but they only return mousemove and mouseout events. I also need keypresses, input, etc. The goal is to capture the events and send them to another client by using websockets, and then replicate them on the other side (co-browsing).
I am using a page on the same domain within the frame.
public class ESinkFrame extends Frame implements EventListener {
public ESinkFrame(String src){
super(src);
DOM.sinkEvents(getElement(), Event.KEYEVENTS);
DOM.sinkEvents(getElement(), Event.MOUSEEVENTS);
}
public void onBrowserEvent(Event event) {
System.out.println( "sunk event: " + DOM.eventGetTypeString(event) );
}
}
And when I use it, I also try to attach a different way of grabbing the events.
ESinkFrame frame = new ESinkFrame("http://127.0.0.1:8888/other.html");
RootPanel.get().add(frame);
FrameElement frameElt = frame.getElement().cast();
Document frameDoc = frameElt.getContentDocument();
BodyElement body = frameDoc.getBody();
Element el = body.cast();
DOM.setEventListener(el, new EventListener()
{
public void onBrowserEvent(Event event)
{
Window.alert("test");
}
});
DOM.sinkEvents(el, Event.KEYEVENTS);
Event.addNativePreviewHandler(new NativePreviewHandler(){
public void onPreviewNativeEvent(NativePreviewEvent event) {
String eventName = event.getNativeEvent().getType();
if (event.isFirstHandler() /* && (event.getTypeInt() & Event.MOUSEEVENTS) == 0*/)
System.out.println("PreviewHandler: " + eventName);
}
});

MVVM - View loading and eventhandling

In my windows phone app, I need to track some events to get a good flow. But I'm not sure how to handle them in good sequence.
What needs to be done at startup of the app:
Main view is loaded and corresponding view model instantiated
In the constructor of the view model I initiate a login sequence that signals when completed with an eventhandler
Now when the login sequence has finished AND the view is completely loaded I need to startup another sequence.
But here is the problem, the order of these 2 events 'completing' is not always the same...
I've use the EventToCommand from MVVMLight to signal the view model that the view has 'loaded'.
Any thoughts on how to synchronize this.
As you should not use wait handles or something similar on the UI thread. You will have to sync the two method using flags in your view model and check them before progressing.
So, implement two boolean properties in your view model. Now when the login dialog is finished set one of the properties (lets call it IsLoggedIn) to true, and when the initialization sequence is finished you set the other property (how about IsInitialized) to true. The trick now lies in the implementation of the setter of these two properties:
#region [IsInitialized]
public const string IsInitializedPropertyName = "IsInitialized";
private bool _isInitialized = false;
public bool IsInitialized {
get {
return _isInitialized;
}
set {
if (_isInitialized == value)
return;
var oldValue = _isInitialized;
_isInitialized = value;
RaisePropertyChanged(IsInitializedPropertyName);
InitializationComplete();
}
}
#endregion
#region [IsLoggedIn]
public const string IsLoggedInPropertyName = "IsLoggedIn";
private bool _isLoggedIn = false;
public bool IsLoggedIn {
get {
return _isLoggedIn;
}
set {
if (_isLoggedIn == value)
return;
var oldValue = _isLoggedIn;
_isLoggedIn = value;
RaisePropertyChanged(IsLoggedInPropertyName);
InitializationComplete();
}
}
#endregion
public void InitializationComplete() {
if (!(this.IsInitialized && this.IsLoggedIn))
return;
// put your code here
}
Alternatively you can remove the InitializationComplete from the setters and change InitializationComplete to:
public void InitializationComplete() {
// put your code here
}
Then subscribe to the 'PropertyChanged' event use the following implementation:
private void Class1_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
if (e.PropertyName == IsInitializedPropertyName || e.PropertyName == IsLoggedInPropertyName) {
if (this.IsInitialized && this.IsLoggedIn)
InitializationComplete();
}
}

Resources