Can I add Custom Control as Marker to OSMBONUSPACK?
I create some Buttons and image in Android xml file Named MyMarkerItem.xml
I would like something like MyMarker.setDesign(R.layout.MyMarkerItem);
Thanks
OK, I understand that you want the marker icon itself to be not a simple bitmap, but a layout.
What you can do is to use the marker infowindow "instead" of the marker icon.
First of all, create a new class CustomInfoWindow which inherits from MarkerInfoWindow - the default InfoWindow for Markers, and uses your own layout:
public class CustomInfoWindow extends MarkerInfoWindow {
public CustomInfoWindow(MapView mapView) {
super(my_own_layout, mapView);
}
}
CustomInfoWindow myCustomInfoWindow = new CustomInfoWindow(mapView);
Then, just after creating your Marker, do that:
Set a marker icon as a 1x1 pixel size bitmap, fully transparent: setIcon(mySmall_InvisibleIcon)
Set the marker infowindow to your own: setInfoWindow(myCustomInfoWindow)
Set the infowindow "anchor" to the most appropriate and natural position, depending on the "look" of your layout: setInfoWindowAnchor(ANCHOR_CENTER, ANCHOR_CENTER) maybe?
Force the opening of the infowindow: showInfoWindow()
All these steps are fairly simple.
But then, I guess you expect some behaviour to happen when the user will click on your layout buttons.
So, inside your CustomInfoWindow code, you will certainly have to do some work => follow this tutorial.
Markers in Osmdroid arent actually android views and therefore it's not possible to add other components into them. They are basically just an image.
Simple and suggested solution
You can add your components to a MarkerInfoWindow which is displayed after a click, though.
marker.setInfoWindow(new MarkerInfoWindow(R.layout.MyMarkerItem, mapView));
Possible "real" soluiton
If you really need such behaviour - meaning you really need multiple buttons displayed on a map as a "marker" and give the user the opportunity to click on them - it should be possible to create your own implementation of a Marker-like class. In other words, you would have to implement your own subclass of OverlayWithIW or Overlay and override (mainly) the draw method (which should draw your buttons to a canvas) and the onSingleTapConfirmed method, where you would need to detect properly on which button user clicked and call the related action. Try to go through source of the Marker class, it's a good example.
But keep in mind: this is an advanced task. Everything related to drawing on canvas can lead to performance issues if it's not done properly. There will be edge cases you'll have to cover. There may be other problems you'll need to solve and debug. I would not suggest such a solution to a beginner.
It's August 2021 and I wanted to add an arbitrary layout as my marker item. Much as the OP is asking for here.
I tried the Simple and suggested solution of https://stackoverflow.com/a/53003664/866333:
marker.setInfoWindow(new MarkerInfoWindow(R.layout.MyMarkerItem, mapView));
I get a runtime exception when I click it:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference.
I refine my layout down to a single TextView widget for arguments sake and the error persists.
I give up on that answer and attempt the accepted one: https://stackoverflow.com/a/53216542/866333
public class CustomInfoWindow extends MarkerInfoWindow {
public CustomInfoWindow(MapView mapView) {
super(my_own_layout, mapView);
}
}
CustomInfoWindow myCustomInfoWindow = new CustomInfoWindow(mapView);
Using the same my_own_layout as before, let's call it R.layout.my_info_window
I get the same error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
I dug into the AS-reverse engineered (thanks AS) source code to discover the reason for this error is that the layout being passed to the MarkerInfoWindow super class constructor has particular id requirements.
We must have these ids in our layout: bubble_title, bubble_description, bubble_subdescription, bubble_image
Here is a minimal working example:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/bubble_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
tools:layout_editor_absoluteX="153dp"
tools:layout_editor_absoluteY="20dp" />
<TextView
android:id="#+id/bubble_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
tools:layout_editor_absoluteX="153dp"
tools:layout_editor_absoluteY="39dp" />
<TextView
android:id="#+id/bubble_subdescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
tools:layout_editor_absoluteX="153dp"
tools:layout_editor_absoluteY="58dp" />
<ImageView
android:id="#+id/bubble_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/marker_cluster"
tools:layout_editor_absoluteX="145dp"
tools:layout_editor_absoluteY="76dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
That works great!
I can even attempt to customise by appending another widget:
<TextView
android:id="#+id/anothertexttestview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="look ma!"
tools:layout_editor_absoluteX="153dp"
tools:layout_editor_absoluteY="125dp" />
The absoluteY is ignored and superimposed on the only text I set programmatically, the title. IOW, the widget isn't purely declarative xml. I'm afraid ConstraintLayout is after my time as a front end engineer so I'll leave it to the reader to experiment from here.
Related
I am making a simple game as a project that is basically a simple version of Galaga with some modifications. I am very new to android and Java (primarily a C++ person) so at first I just made the ship automatically move right and holding down on the screen makes the ship move left. I did this to keep it simple (as it was easy to implement an on-touch listener within my GameView for this task) so that I could finish the rest of the basic framework of the app before going back and improving the functionality of particular bits.
Right now my GameView is created programmatically within GameActivity and then "setContentView()" is used to set the activity's view to the new GameView:
public class GameActivity extends AppCompatActivity {
private GameView gameView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
gameView = new GameView(this, size.x, size.y);
setContentView(gameView);
}
Now what I want, is two small buttons in the corner of the screen that move the ship left and right, but I am stuck on how to easily do this because each way I keep thinking of gets really complicated (mostly due to being an android novice).
The two best ways I can think of are as follows:
1) Use the Android Studio XML design tool to place the buttons and my custom SurfaceView (GameView) into the proper locations and then just use "setContentView(R.layout.activity_game)" within my GameActivity.
This would be great; however, there's two problems I cannot figure out how to overcome. First, when I drag "view" into the layout for GameActivity and select my custom SurfaceView "GameView" in the pop-up window, I get an error:
and additionally, as you can see in the code I posted, a GameView needs to be passed two integers whenever it is created and I don't see how I could make this happen if I just put a GameView in my XML layout with the designer.
2) Continue creating the GameView programmatically like I am, setup the GameActivity layout using the designer to contain all the buttons I need, then programmatically add the GameView (custom SurfaceView) to the GameActivity layout before finally using "setContentView(R.layout.activity_game)". This seems the most simple to me, but I don't know how to grab a reference to the entire XML layout that's created with the activity by default (activity_game.xml) and then add the created GameView to it. I can only find code examples for using "findViewById()" to reference pieces of an XML made layout (like a button, or linear layout within the XML made layout). I imagine I might be able to create a Frame layout or something similar within the XML designer and then attach everything to that and use "findViewById()" to attach my GameView to the frame, but I don't know if that would work. Finally, I have a feeling that because the buttons on the XML layout would have existed first, programmatically adding the GameView would mean that the buttons would get covered up and I don't know how to avoid that.
Sorry for the long-winded question but I just couldn't find any sample code or previous questions/answers that addressed this specifically, I could only find bits and pieces that I wasn't sure how to put together.
Any help on the easiest way to have my buttons created in "activity_game.xml" appear on-top of my programmatically created GameView so I can easily position the buttons and easily grab them by ID for on-click listeners?
EDIT:
As requested this is the current setup for activity_game.xml, the frame layout is just there as part of my experimentation but is not actually being used right now since the content view for the activity is set to GameView. I have the button just floating there because right now I am just trying to get it to show up and will worry about proper implementation once I reach that point:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_game"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.chrisheimlich.galaticrenegade.GameActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/testFrame"
android:layout_alignParentStart="true">
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="113dp"
android:layout_marginTop="14dp"
android:id="#+id/button2" />
</FrameLayout>
In my app, users can either take a picture or record a video. The file is then saved and its path is passed through an intent to the next activity, which displays it for editing.
My question is, how can I easily use the same view for either a video or an image?
I tried dynamically adding a view at runtime when I know what the file type is, but it turned out to be too hard to configure, not to mention the issues that VideoViews have with being rotated.
Edit:
I forgot to mention that using the same view would be preferable, since I'm not actually going to do anything to the contents that's specific to each kind of view.
Add both the ImageView and VideoView in your layout. Then set the visibility to GONE or VISIBLE for the one you want.
You can create two child views, one for the image and one for the video. And depending on the type of your view you can hide/show your child views.
You can also use FrameLayout for this
By using frame layout / Relative layout you can place a view on top of another view. After creating the views like i mention and using the visibility Gone & Visible you can manage to handle it..
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/ImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/my_drawable"
android:scaleType="fitCenter"
android:visibility="gone"/>
<VideoView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:padding="5dp"
android:id="#+id/VideoView"
android:visibility="gone"/>
</FrameLayout>
Then based on your usage you can control it dynamically like below
// register the views
ImageView mImageView= (ImageView)findViewById(R.id.ImageView);
VideoView mVideoView= (VideoView)findViewById(R.id.VideoView);
// check your conditions like show video view r image view here
if(VideoView)
{
mVideoView.setVisibility(View.VISIBLE);
mImageView.setVisibility(View.GONE);
}
else if(ImageView)
{
mImageView.setVisibility(View.VISIBLE);
mVideoView.setVisibility(View.GONE);
}
Hope it will work for you :)
I'm making an app for Android with Java in eclipse, and it will have multiple screens. One screen will contain a canvas with 2D graphics, and some buttons below the canvas. But I'm a newbie at Android so it's still a little messy to me. Seems like a new Paint() in a class which extends View always is fullscreen (?) so I tried to solve it with Fragments where I put the canvas/newPaint() in one Fragment and the buttons in another one. But my app crashes when I try to add the Fragments in the xml file, and I don't know why.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/game_fragment"
android:name="com.example.tictactoe.GameFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:background="#FF0000"
tools:layout="#layout/game_view" />
<fragment
android:id="#+id/game_fragment2"
android:name="com.example.tictactoe.GameFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FFFF00"
tools:layout="#layout/game_view" />
Is there any other way of getting a 2D graphics canvas together with some buttons on a screen,
or can someone help me out with the fragment solution?
Thanks in advance!
Your stacktrace gives what the error is - GameFragment is not a class inheriting from Fragment. You need to ensure that you are placing Fragment classes appropriately in your layout.
Also from looking at your layout, you are placing GameFragment layout twice in the same root view. This looks wrong on some level. I mean if you have your buttons in a different layout, shouldn't you be using that layout? Also, as a tip, inflate the layout for the fragment by overriding the GamrFragment's onCreateView() method (you should see this method once you have inherited from the Fragment class appropriately).
And last but not the least, when using Fragments, ensure that you use the right version uniformly (if you use the fragments from the support package, stick to using it uniformly).
Using android, I'd like to get a vertical switch widget implementation in place. As far as I can tell, it looks like switches only have a horizontal orientation. I'd like to have something like the following:
After looking through the threads here and searching google, I have yet to find something that can give me this. Everything I search for gives me the horizontal implementation only.
so I can generate your typical horizontal switch
<Switch
android:id="#+id/switch_button"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/label"
android:layout_gravity="center"
android:switchMinWidth="130dp"
android:thumb="#drawable/switch_selector"
android:track="#drawable/track_selector" >
</Switch>
but there doesn't seem to be a good way to set the orientation. I know that the question is a bit high level. Is there some attribute that is immediately available that will allow me to have a vertical switch? Or will I have to create a custom switch and possibly modify the onDraw method so that it is flipped vertically? Any help is appreciated. Thanks.
Try android:rotation="90" like this:
<Switch
android:id="#+id/switch_button"
android:layout_width="130dp"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/label"
android:layout_gravity="center"
android:switchMinWidth="130dp"
android:thumb="#drawable/switch_selector"
android:track="#drawable/track_selector"
android:rotation="90">
</Switch>
There is no quick attribute for vertical orientation.. Sorry :)
First you can look at the code of the switch and see if you can copy and manipulate it.
Second you can just implement your on. Have a layout with a button inside it. use onTouchListener to slide it from side to side. No need to use "onDraw".
Try toggle button witch graphics and use pictures like this You included in Your post. Here is example of such toggle buttons: Toggle button using two image on different state
I've developed apps and games in the past. Now I'm doing one which is a mixture (don't ask..)
Anyhow I was wondering if was possible to draw a custom loop within the view, example.
I want to do this so achieve complete control loops. Maybe a master loop on top of the view's that's always running (If that's possible).
Relative Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
/>
Within the layout would it be possible to implement a loop as such (obviously in another thread with a bit more code for checking etc etc)
Canvas draw loop
RectF CustomViewWidthAndHeight = new RectF(); //Set using view ID.
do
{
//Using circle as an example.
canvas.drawCircle(Blag, XY);
XY++; //An example.
}
while(endLoopSometime)
How would one go about implementing this if it's wise too, or advising me of another method.
It sounds like you are trying to build your own Custom View. The Android team has been improving the documentation on the Android Developer website. There is a tutorial in the training section on Creating Custom Views which should get you started.