SKMaps in Android not displaying annotations - android

I had created a demo app to known about SKMaps, it worked good with adding annotations. However, now I have moved the code to actual project with the same requirements. Added annotations is not being displayed. I tried with both SKAnnotationView (custom view) and default Annotation type like SKAnnotation.SK_ANNOTATION_TYPE_RED and SKAnnotation.SK_ANNOTATION_TYPE_PURPLE. Nothing is being added to the map.
I have a custom view pager in the same screen, I removed the same and checked still didn't work. SKMapViewHolder is added dynamically.
Code snippet for adding SKMapViewHolder dynamically:
SKMapViewHolder mMapHolder = new SKMapViewHolder(OfflineMapScreen.this);
mMapHolder.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
RelativeLayout outerLayout = (RelativeLayout) findViewById(R.id.outer_layout);
outerLayout.addView(mMapHolder);
RelativeLayout.LayoutParams rlp = (android.widget.RelativeLayout.LayoutParams) mMapHolder.getLayoutParams();
rlp.addRule(RelativeLayout.BELOW, R.id.header);
mMapHolder.setLayoutParams(rlp);
mOSMMapView = mMapHolder.getMapSurfaceView();
mOSMMapView.setMapSurfaceListener(this);
mOSMMapView.getMapSettings().setFollowerMode(SKMapFollowerMode.NONE);
mOSMMapView.getMapSettings().setMapPanningEnabled(true);
mOSMMapView.getMapSettings().setInertiaPanningEnabled(true);
mOSMMapView.getMapSettings().setCompassShown(false);
mOSMMapView.getMapSettings().setCurrentPositionShown(false);
mOSMMapView.setZoomSmooth(14f, 500);
Anybody has the solution for this? Code snippet of adding annotations can be seen here: http://postimg.org/image/sdbwzej9z/

In the image you provided we have noticed that when setting the location you are reusing the same value for both latitude and longitude. Use something like:
annotationDrawable.setLocation(new SKCoordinate(Double.valueOf(aPlace.getLongitude()),Double.valueOf(aPlace.getLatitude())) ;

Related

Use two osmdroid Map Views in one Activity

I want to use two Map Fragments, each with a different fragment, side-by-side in an activity. The left map is planned to show a overview over a specific area, the right one zooms in to a specific point.
The problem I'm having is, that only the first (left) map fragment is being correctly shown, the second (right) one shows a world map:
Zooming is not working on the right map.
Here is a part of the code I'm using:
private void initializeMap()
{
MapTileProviderBasic tileProviderOSM = new MapTileProviderBasic(getApplicationContext());
ITileSource tileSourceOSM = new XYTileSource("OpenFireMap", null, 1, 18, 256, ".png", new String[]{"http://openfiremap.org/hytiles/"});
tileProviderOSM.setTileSource(tileSourceOSM);
TilesOverlay tilesOverlayOSM = new TilesOverlay(tileProviderOSM, this.getBaseContext());
tilesOverlayOSM.setLoadingBackgroundColor(Color.TRANSPARENT);
OsmFragment frag = (OsmFragment) getFragmentManager().findFragmentById(R.id.osmMap);
osmMap = frag.getMap();
osmMap.setMultiTouchControls(true);
osmMap.getOverlays().add(tilesOverlayOSM);
MapTileProviderBasic tileProviderOSMDetail = new MapTileProviderBasic(getApplicationContext());
ITileSource tileSourceOSMDetail = new XYTileSource("OpenFireMap", null, 1, 18, 256, ".png", new String[]{"http://openfiremap.org/hytiles/"});
tileProviderOSMDetail.setTileSource(tileSourceOSMDetail);
TilesOverlay tilesOverlayOSMDetail = new TilesOverlay(tileProviderOSMDetail, this.getBaseContext());
tilesOverlayOSMDetail.setLoadingBackgroundColor(Color.TRANSPARENT);
OsmFragment fragDetail = (OsmFragment) getFragmentManager().findFragmentById(R.id.osmMapDetail);
osmMapDetail = fragDetail.getMap();
osmMapDetail.setMultiTouchControls(true);
osmMapDetail.getOverlays().add(tilesOverlayOSMDetail);
}
If I change either one of the fragments to a GoogleMaps fragment, the osmdroid map loads correctly.
Any ideas why this is happening and how I can fix it? I'm using the newest osmdroid version from gradle (v5.6.4)
Thanks in advance.
EDIT:
I changed the variable declation, but it still doesn't work.
You have to create separate TilesOverlays for different map views. Currently you are using the single overlay in two fragments, this can not work.
So I found the solution. The problem was, that the MapView is within a fragment and the fragment is a custom class which had the hardcoded ID's and layouts in it. The solution which worked for me was duplicating the custom fragment class and editing the ID and Layout. Then in MainActivity I had to change the varaible declaration and the cast from OsmFragment to OsmFragmentDetail
Now both maps are showing the wanted content.

PopupWindow.getContentView().getLayoutParams() returns a different class in Android Marshmallow

I am having a code such as below.
....
PopupWindow popupWindow = new PopupWindow(someView);
final WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) popupWindow.getContentView().getLayoutParams();
....
The problem popupWindow.getContentView().getLayoutParams is returning differnt classes as below because of which my typecast is failing
Before Marshamallow : android.View.WindowManager.LayoutParams
For Marshmallow : android.widget.FrameLayout.layoutParams
Has anyone faced the issue before or any resolutions please?
That's right. M wraps everything inside a FrameLayout called mDecorView. If you dig into the PopupWindow source you will find something like createDecorView(View contentView). The main purpose of mDecorView is to handle event dispatch and content transitions, which are new to M.
To get a hold of your contentView try:
View container = (View) popupWindow.getContentView().getParent();
container.getLayoutParams();
Keep in mind that if your contentView's background is not null it will be nested twice. This would mean: (View) popupWindow.getContentView().getParent().getParent();

How to modify a Skobbler Annotation without re adding it

I have to modify the image of a SKAnnotation.
Annotation builder code:
private SKAnnotation getAnnotationFromView (int id,int minZoomLvl, View view) {
SKAnnotation annotation = new SKAnnotation();
SKAnnotationView annotationView = new SKAnnotationView();
annotationView.setView(view);
annotation.setUniqueID(id);
annotation.setOffset(new SKScreenPoint(annotationView.getWidth()/2, annotationView.getHeight()/2));
annotation.setAnnotationView(annotationView);
annotation.setMininumZoomLevel(minZoomLvl);
return annotation;
}
Now my problem is to update the annotation/image to the current state (position, orientation). Is there a way doing that without re adding the annotation? Looking into the documentation I found mapView.updateAnnotation() but it seems to work just for images added with annotation.setImagePath(imagePath)
Can someone help me with that?
Unfortunately no.
There is an inconsistency in the implementation (we'll address that in a future update) that allows one to reposition only annotations with the icon taken from an file.
If you'd like to reposition an (any) annotation you could/should remove it and add it again.
If you'd like to change the icon/view - then the updateAnnotation API should do the job

Copy the rules of RelativeLayout.LayoutParams before API 19

Im trying to copy RelativeLayout.LayoutParams, and i need the new Params to be exactly like the old ones. So consider this method:
private RelativeLayout.LayoutParams copyParams(RelativeLayout.LayoutParams source){
RelativeLayout.LayoutParams copy = new RelativeLayout.LayoutParams((RelativeLayout.LayoutParams)source);
return copy;
}
Now, this works all right, but it will only compile above API-Level 19, as eclipse conveniently tells me.
To make this work pre-API-19, i tried this:
private RelativeLayout.LayoutParams copyParams(RelativeLayout.LayoutParams source){
RelativeLayout.LayoutParams copy = new RelativeLayout.LayoutParams((ViewGroup.LayoutParams)source);
copy.setMargins(source.leftMargin, source.topMargin, source.rightMargin, source.bottomMargin);
return copy;
}
By casting to ViewGroup.LayoutParams, i can force the use of the ViewGroup.LayoutParams CopyConstructor. It is readily available, but it will only copy the height and width. So i need to transfer the margins myself, which i do in line 3 of example 2. But this still leaves out the rules in the source layout, like RelativeLayout.BELOW, for example.
I can't find a copyRules() or setRules() method (or anything equivalent) anywhere in the docs, but i can see the addRule() method of RelativeLayout.LayoutParams. Considering that source.getRules() returns an Array i think i could loop over that and add each rule to my new LayoutParams, but that feels like im doing it wrong. Is there a sane way to copy these rules?
TL;DR: Before API 19, is there a way to copy the rules of RelativeLayout.LayoutParams wholesale, and if not, what is the least insane way to copy them at all?
well, if clone didn't work, probably your last resort will be a good ol' fashioned for-loop uh.
use getRules() to get the list of rules in the current LayoutParams and addRule(int, int) to add them to a new LayoutParam.
old answer:
In this case I would try .clone.
LayoutParams in general are very simple objects with just a few integers, so .clone should handle it nicely.
original answer:
try:
RelativeLayout.LayoutParams copy = new RelativeLayout.LayoutParams((ViewGroup.LayoutParams)source);
the constructor with ViewGroup.LayoutParams exist since API 1.
ps.: Even thou I know it will compile, I strongly suggest you to double check that all the parameters were properly copied over (not just with, height n margins)
Here is what I did to copy a RelativeLayout.LayoutParams with all its rules:
#NonNull
private static RelativeLayout.LayoutParams copy(ViewGroup.LayoutParams viewLayoutParamsToCopy) {
RelativeLayout.LayoutParams copiedParams = new RelativeLayout.LayoutParams(viewLayoutParamsToCopy);
if (viewLayoutParamsToCopy instanceof RelativeLayout.LayoutParams) {
RelativeLayout.LayoutParams relativeLayoutParamsToCopy = (RelativeLayout.LayoutParams) viewLayoutParamsToCopy;
int[] rulesToCopy = relativeLayoutParamsToCopy.getRules();
for (int verb = 0; verb < rulesToCopy.length; verb++) {
int subject = rulesToCopy[verb];
copiedParams.addRule(verb, subject);
}
}
return copiedParams;
}
To make it work I had to carefully read the documentation of the getRules() method:
Retrieves a complete list of all supported rules, where the index is the rule verb, and the element value is the value specified, or "false" if it was never set.

How to Shrink WebView size dynamically according to its content?

A detailed explanation of issue can be understood from this question as the user had added image to explain it better.
I am loading Html content in my WebView. My layout is having many view and WebView is place inside ScrollView(as per layout requirement). Please don't answer as - "Don't put WebView inside ScrollView". I know that its not a good thing to put WebView inside a ScrollView, but as per requirement I need to do so.
So, I have Left Fragment(showing List Items) and Right Fragment(Showing data reflected on selection of List Item from Left Fragment). Now, first of all when I load Html content inside WebV it shows correct. After that when I refresh WebView with new Html content the problem occurs.
Suppose, my first Html content is of 100 lines it shows correctly and then I reload WebView with my new Html content which is of 40 lines then the WebView is not shrinking and fitting to the content with 40 lines, it still remains as long as 100 lines showing white/blank space at the bottom.
So, it seems that WebView is able to re-size itself from less content which is previously loaded to more content but unable to re-size itself when the content is less than previously loaded content.
I had tried many ways,
Adding android:hardwareAccelerated="true" in Manifest
This Blog
Also many other ways and blog
Also I had tried to use mWebView.clearView(); which causes to re-size the size of WebView but at times the WebView start blinking which is just annoying. Similar to this video
But, couldn't find any proper solution. If anyone of you have the same issue before just let me know the best solution I could apply.
UPDATE -
After further googling it seems that this is a well-known issue in Honeycomb. This question also indicates the similar issue.
Seems there's no way to resize the WebView(decrease) its size dynamically once its loaded. So, the only thing that could solve my problem was reloading the complete WebView.
So, instead of defining the Fragment in XML, I changed my stuff by adding Fragment dynamically every time. By which I was able to solve my issue.
This is a known problem with WebView and some available solution doesn't work in all the devices.
I tried many solution given in SO answers and also searched over the internet but none of them worked for me too.
I ended up , removing the WebView and adding the WebView again at the same position in in Layout
Here is that demo code,
final RelativeLayout rl = new RelativeLayout(this);
myWebView = new WebView(this);
myWebView.setBackgroundColor(Color.GRAY);
myWebView.loadUrl("file:///android_asset/1.htm");
rl.addView(myWebView); // ******* Added At Index 0
Button btn = new Button(this);
btn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (!flg) {
rl.removeViewAt(0);
myWebView = new WebView(MainActivity.this);
myWebView.setBackgroundColor(Color.GRAY);
myWebView.loadUrl("file:///android_asset/3.htm");
rl.addView(myWebView, 0, new RelativeLayout.LayoutParams(
new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT)));
flg = true;
} else {
rl.removeViewAt(0);
myWebView = new WebView(MainActivity.this);
myWebView.setBackgroundColor(Color.GRAY);
myWebView.loadUrl("file:///android_asset/1.htm");
rl.addView(myWebView, 0, new RelativeLayout.LayoutParams(
new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT)));
flg = false;
}
}
});
rl.addView(btn); // ******* Added At Index 1
setContentView(rl);
guys, it seems I found a solution for local content. You should just call webView.reload() before loading new content - somehow it does the resizing without any blinking.
Here I have changed the height of webview depending of softkeyboard display
activityRootView = (RelativeLayout) findViewById(R.id.webview1);
mWebView = (WebViewEx) WebViewActivity.this.findViewById(R.id.webview);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
Rect r = new Rect();
//r will be populated with the coordinates of your view that area still visible.
activityRootView.getWindowVisibleDisplayFrame(r);
int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
if(heightDiff != lastValue) {
if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
Log.i("Screen Size Changed","KeyBoard Displaying"+ r.bottom);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.height=r.bottom;
mWebView.setLayoutParams(params);
//appView.sendJavascript("onKeyBoardShow(" + r.bottom + ");");
} else {
/// appView.sendJavascript("onKeyBoardHide();");
Log.i("Screen Size Changed","KeyBoard not displaying" +r.bottom);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.height=r.bottom;
mWebView.setLayoutParams(params);
}
lastValue = heightDiff;
}
}
});
i have not tried but why dont you give a try by setting weblayout params again, before u load the new contents. ie set height and width to wrapcontent. if success found please reply. if wont find success better go for javascipt
I set the visibility of my WebView to Gone, and load the content into the WebView while it's gone. Then I set the visibility to visible after letting the DOM and JS load and it seems to draw the length correctly. Since there isn't a callback like onPageFinished for determining when the JS has finished executing, I give the WebView a one second delay before I set the visibility to true. This workaround suffices for my purposes, so hopefully it addresses the needs of some of you guys!
Everytime creating an object of webview and give its param is a pain instead you can do following steps and it will work
put a blank html file in assets folder and give it a name
empty.html
call webview.loadUrl("file:///android_asset/empty.html");
now load your content.
Webview will shrink its height.
Make sure you are not putting any content in empty.html
This do the magic! It says
Android property: android:layout_weight = "1 in the layout should work...
In my case, WebView is in the RelativeLayout. So doing thi android:layout_height="wrap_content" worked like a charm :)
As #Ankit pointed out, go to an empty page could help. "about:blank" is better, though.

Categories

Resources