Android Google Maps API - align custom button with existing buttons - android

I'm trying to display a custom button on a googlemap.
<Button
android:id="#+id/button_backHome"
android:layout_alignParentRight="true"
android:layout_marginTop="50dp"
android:layout_marginRight="11.5dp"
android:layout_height="39dp"
android:layout_width="39dp"
android:background="#drawable/custom_button"
/>
This displays the button directly below googlemap's Set Camera to Current location button in the top right of the screen, but obviously only on my test device. On other devices these settings don't align the button correctly.
XXHDPI (galaxy S4)
XHDPI (Nexus 10)
What would be a good solution, other then making all the buttons myself? Could I inherit the margins from the google button without knowing the style's name?
I'm pretty much at a loss here, and any help would be Much apreciated.
Thanks in advance!

Parent Layout for Google Maps map is RelativeLayout so best approach for custom button alignment with default Google Maps control button (for all screens) is to put that custom button into same layout as default Google Maps control button. Assume our activity with Google Maps map has layout like:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="<YOUR_PACKAGE>.MainActivity">
<fragment
android:id="#+id/map_fragment"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="#+id/custom_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:visibility="gone"
android:src="#drawable/ic_home_target"/>
</RelativeLayout>
As custom button View is better to use ImageView, because the default buttons layouts has 9 patches padding in them (details here), or it's necessary to set additional padding to default Google Maps control button. Now it belongs to activity layout. So in onMapReady(GoogleMap googleMap) we should:
1) get parent View for default Google Maps control button;
2) remove custom button view from root activity layout;
3) add custom button view to parent View for default Google Maps control button (defined in p.1);
4) set alignment for custom button view relative to default Google Maps control button.
With Source code like this:
...
private GoogleMap mGoogleMap;
private MapFragment mMapFragment;
private ImageView mCustomButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCustomButton = (ImageView) findViewById(R.id.custom_button);
mMapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mMapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
// don't forget to allow LOCATION permission
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (locationPermission == PackageManager.PERMISSION_GRANTED) {
setConrolsPositions();
}
} else {
setConrolsPositions();
}
}
void setConrolsPositions() {
try {
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
// get parent view for default Google Maps control button
final ViewGroup parent = (ViewGroup) mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton").getParent();
parent.post(new Runnable() {
#Override
public void run() {
try {
// get view for default Google Maps control button
View defaultButton = mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton");
// remove custom button view from activity root layout
ViewGroup customButtonParent = (ViewGroup) mCustomButton.getParent();
customButtonParent.removeView(mCustomButton);
// add custom button view to Google Maps control button parent
ViewGroup defaultButtonParent = (ViewGroup) defaultButton.getParent();
defaultButtonParent.addView(mCustomButton);
// create layout with same size as default Google Maps control button
RelativeLayout.LayoutParams customButtonLayoutParams = new RelativeLayout.LayoutParams(defaultButton.getHeight(), defaultButton.getHeight());
// align custom button view layout relative to defaultButton
customButtonLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, defaultButton.getId());
customButtonLayoutParams.addRule(RelativeLayout.BELOW, defaultButton.getId());
// add other settings (optional)
mCustomButton.setAlpha(defaultButton.getAlpha());
mCustomButton.setPadding(defaultButton.getPaddingLeft(), defaultButton.defaultButton(),
defaultButton.getPaddingRight(), defaultButton.getPaddingBottom());
// apply layout settings to custom button view
mCustomButton.setLayoutParams(customButtonLayoutParams);
mCustomButton.setVisibility(View.VISIBLE);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
and enabled Show layout boundaries option in Developer Options you should get something like that:
As you can see custom button has exactly same size as default button layout and placed exactly below it.
For better result it's necessary to adjust custom button glyph (padding, transparency, colors, etc.)
Or may be easiest way: don't use default Google Maps "GoogleMapMyLocationButton" button at all - set it's Enabled property to false (mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);) but use custom layout with button with same icon and functionality emulated by GoogleMap.animateCamera() on same layout with "target home" custom button.

You have a dpi problems in your posted image, Also in your posted xml you are only using 1 attribute values for all devices android:layout_marginRight="11.5dp" which will fail in other device with higher dpi, except the one you first tried it on.
solution:
Use the values folder with dpi click here to know about it.
What you need is to create a dimens attribute on each of the dpi folder ldpi, hdpi, etc. for the margin
sample:
<resources>
<dimen name="margin_right">11.5dp</dimen> //this is located in hdpi values dimension
</resources>
and another in xhdpi
<resources>
<dimen name="margin_right">greater than hdpi</dimen> //this is located in xhdpi values dimension
</resources>
to use it is to just call #dimension
android:layout_marginRight="#dimension/margin_right"
now using this solution will enable your device to pick the right value of the margin on different devices.

Related

Write text in Google Map v2 custom marker - Android

In my map , I have some list of Markers, now I need to achieve the output as like below
i.e. marker with index number.
I have searched over google but didn't get any solution, Please help me to get an idea to implement this.
Do whatever you want with Google Map Markers
I have made a very flexible and interesting hack to achieve whatever kind of marker you want.
What I do is,
Create an XML Layout file and design it the way you want your marker to appear. For example in your case it is going to be a Green Marker image with a TextView on it.
Set the values of TextViews as per requirement.
Convert the Layout file to an image and get BitmapDescriptor Object.
Create a custom marker by using the image you just created.
The benefit of such view over Info Window is that you can open window for multiple markers at same time. As in InfoWindow you can open it only for one marker at one time.
Code Sample
Check out my this answer for Code Help.
For custom marker:
You can create a custom image and draw an index number in top of
that image
Check this example for custom marker
For Marker Window:
You can create a custom xml file that contains ImageView and TextViews:
Something like customMapView.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#color/white_full"
android:layout_width="match_parent"
android:padding="#dimen/padding_micro"
android:layout_height="match_parent">
<ImageView
android:id="#+id/img"
android:layout_gravity="left"
android:src="#drawable/ic_launcher"
android:textColor="#color/black_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:gravity="right"
android:id="#+id/name"
android:text="test"
android:textColor="#color/black_full"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Other TextViews or Whatever you want-->
</RelativeLayout>
After you initialize Markers you call setInfoWindowAdapter and inflate your custom view. Something like:
private void customizeMarkerInfoWindow(){
//Setting custom info window
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
//Use default infoWindow frame
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
// Getting view from the layout file
View view = mActivity.getLayoutInflater().inflate(R.layout.customMapView, null);
// Getting the position from the marker
LatLng latLng = marker.getPosition();
//UI elements
ImageView img = (TextView) view.findViewById(R.id.img);
TextView coord = (TextView) view.findViewById(R.id.name);
mukAdTv.setText(mukAd);
//You set the image here depending on how you want to set it, if you are downloading from internet you can use PICASSO for it and set it to img
//With picasso
Picasso.with(mActivity).load(YOUR_IMAGE_URL).into(img);
//From drawables
//img.setBackground(yourDrawable);
name.setText(latLng.latitude + ", " + latLng.longitude);
return view;
}
});
}

How would you create a popover view in Android, like Facebook Comments?

I was wondering if anyone knows how to create a Facebook-like popover view like in the Facebook Android app for comments.
This is what I mean:
Along with the handle that you can drag to dismiss it, is it a native Android UI control or has Facebook implemented this themselves?
The best way to create similar popover view is by using PopupWindow, since you can place the PopUpWindow on any of the specific view position (or on center/top/bottom of screen). You can also achieve same UI with DialogFragment , but you cannot position at specific view location.
I have a complete working code here https://gist.github.com/libinbensin/67fcc43a7344758390c3
Step 1: Create your custom layout , for e.g., as Facebook its has a Header TextView with a ListView and EditText.
Step 2: Set the layout to the PopupWindow
Inflate the layout to set
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View inflatedView = layoutInflater.inflate(R.layout.fb_popup_layout, null,false);
This Layout has a ListView ,so find the ListView in the layout and fill the data . you can have your own view here
ListView listView = (ListView)inflatedView.findViewById(R.id.commentsListView);
listView.setAdapter(new ArrayAdapter<String>(TryMeActivity.this,
R.layout.fb_comments_list_item, android.R.id.text1,contactsList));
Now, create an instance of PopupWindow with specific height and width. I prefer to set the size depends on the device.
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
popWindow = new PopupWindow(inflatedView, size.x - 50,size.y - 500, true );
Set the focusability of the popup window.
popWindow.setFocusable(true);
Make it outside touchable to dismiss the popup window when touched outside the popup area
popWindow.setOutsideTouchable(true);
Now, set a background to the PopupWindow with a drawable. The drawable has rectangle shape with corner radius.
popWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.fb_popup_bg));
Finally. show the PopupWindow at required location. I made it show at bottom of the screen with some X and Y position
popWindow.showAtLocation(v, Gravity.BOTTOM, 0,150); // 0 - X postion and 150 - Y position
You can also set an Animation to use when the PopUpWindow appears and disappears
popWindow.setAnimationStyle(R.anim.animation); // call this before showing the popup
Edit:
Actually, even though I used a DialogFragment, I'm quite certain their popup does not use a DialogFragment (or even a Dialog at all!). The reason for this is the resizing feature. If that is something you want, then you can't use a DialogFragment. You would have to just add a new view to your layout. It looks like facebook also has another view that sits between your wall and the fake popup that is slightly translucent and listens for clicks in order to dismiss the view. Something like this would take some actual effort and time to build, so I won't make this one for you. Let me know if you have any questions about it though, I can probably guide you to the solution you are after.
Original:
I wrote the popup for you:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
F1.newInstance().show(getFragmentManager(), null);
}
}
public static class F1 extends DialogFragment {
public static F1 newInstance() {
F1 f1 = new F1();
f1.setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_DeviceDefault_Dialog);
return f1;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Remove the default background
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
// Inflate the new view with margins and background
View v = inflater.inflate(R.layout.popup_layout, container, false);
// Set up a click listener to dismiss the popup if they click outside
// of the background view
v.findViewById(R.id.popup_root).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
return v;
}
}
}
popup_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:id="#+id/popup_root">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="72dp"
android:layout_marginBottom="72dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:padding="20dp"
android:clickable="true"
android:background="#drawable/dialog_background">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textColor="#000"
android:text="Content goes here!" />
</FrameLayout>
</FrameLayout>
And dialog_background.xml (goes into res/drawable):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<solid android:color="#FFF" />
<corners android:topLeftRadius="20dp" android:topRightRadius="20dp"
android:bottomLeftRadius="20dp" android:bottomRightRadius="20dp"/>
<stroke android:color="#7F7F7F" android:width="1dp" />
</shape>
And it looks like this:
Just add your view content and you're good to go!
You can use a PopupWindow to do that. http://developer.android.com/reference/android/widget/PopupWindow.html
Of course you'll need to style it and fill in the popup's contents on your own. You can get some styling ideas from How to make layout with rounded corners..?
This seems like a custom component built by Facebook. It is not a standard Android component. You can try implementing it by deriving from the Dialog Fragment.
It looks like it would be easiest to just use a Fragment with a transparent (or in this case translucent) background.

display view on top of action bar

Is there a way to render a view on top of the action bar? I want to create a small tip box that will point the user to an item in the action bar. I know that a Toast with a set view will be rendered above the action bar. Does anyone know how to do this with a view?
I have attempted using FrameLayout with layout_gravity="top" and inflating a view and then adding it to the running activity's layout.
I appreciate you in advance.
Edit:
Here is an image of what I was thinking:
Edit:
Perhaps some more detail is needed. I am looking for a way, or to find out if it is even possible to add a view to the view hierarchy of the activity so that it is rendered last.
Similar to CSS, I want a higher z-index order for this particular view ( the blue floating box in the image), such that it would be rendered on top of the Action Bar region in the activity. The view is in no way associated with Action Bar, it is simply drawn on top of it.
I was trying to achieve something else but I needed a solution similar to this. I needed to draw an opaque layer covering the whole screen, even the action bar--sort of like a dialog. I did so this way:
ViewGroup vg = (ViewGroup)(getWindow().getDecorView().getRootView());
vg.addView(myNewView, params);
this can be used to draw anything anywhere on the screen.
UPDATE: You really shouldn't be using ActionBar anymore, you wouldn't have this issue in the first place if you were using Toolbar like Android recommends. Toolbar would go inside your activity xml like a regular view and you can can do whatever you want to it. And its fully backwards compatible.
https://developer.android.com/training/appbar/setting-up
After struggling with it myself quite some time, here's the solution (tested it - working good):
The general steps are:
Create a wrapper view
Detach the screen view children, place the wrapper, and attach the children
Inflate the content to the children
Controling the wrapper will help you control exactly the action bar and the content below it all together.
Now, using the wrapper, you can add "brothers" to the actionbar/main area. That brother is exactly what you described in your image.
Let's see some code.
First, create a method to help create a wrapper view. the wrapper will be placed between the entire screen and the content of your app. being a ViewGroup you can later on fully control it's content.
private ViewGroup setContentViewWithWrapper(int resContent) {
ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0);
// Removing decorChild, we'll add it back soon
decorView.removeAllViews();
ViewGroup wrapperView = new FrameLayout(this);
// You should set some ID, if you'll want to reference this wrapper in that manner later
//
// The ID, such as "R.id.ACTIVITY_LAYOUT_WRAPPER" can be set at a resource file, such as:
// <resources xmlns:android="http://schemas.android.com/apk/res/android">
// <item type="id" name="ACTIVITY_LAYOUT_WRAPPER"/>
// </resources>
//
wrapperView.setId(R.id.ACTIVITY_LAYOUT_WRAPPER);
// Now we are rebuilding the DecorView, but this time we
// have our wrapper view to stand between the real content and the decor
decorView.addView(wrapperView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
wrapperView.addView(decorChild, decorChild.getLayoutParams());
LayoutInflater.from(this).inflate(getActivityLayout(),
(ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);
return wrapperView;
}
Now, interfere with the regular Activity creation, and instead of using setContentView, use the method we've created.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// DON'T CALL `setContentView`,
// we are replacing that line with this code:
ViewGroup wrapperView = setContentViewWithWrapper(R.layout.activity_layout);
// Now, because the wrapper view contains the entire screen (including the notification bar
// which is above the ActionBar) I think you'll find it useful to know the exact Y where the
// action bar is located.
// You can use something like that:
ViewGroup actionBar = (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(0);
int topOffset = actionBar.getTop();
// Now, if you'll want to add a view:
// 1. Create new view
// 2. Set padding top - use "topOffset"
// 3. Add the view to "wrapperView"
// 4. The view should be set at front. if not - try calling to "bringToFront()"
}
That's about it.
Notes
I've used Android's hierarchy-viewer to understand what's the right hierarchy. (didn't guess those 0 and 1 indexes)
If you are using some kind of a menu drawer in your activity, you might have to configure it a little bit different since drawers are already creating that wrapper for you
I've learned a lot by looking at this great library
EDIT: Refer to #CristopherOyarzĂșnAltamirano Answer for further support on newer Android versions
Good luck!
There is a much simpler way to achieve this. ActionBar holds its layout in the class ActionBarContainer which simply inherits from FrameLayout. So in order to display something over the ActionBar you need to grab a reference to the ActionBarContainer and add your own custom View into it. Here is the code
int abContainerViewID = getResources().getIdentifier("action_bar_container", "id", "android");
FrameLayout actionBarContainer = (FrameLayout)findViewById(abContainerViewID);
LayoutInflater myinflater = getLayoutInflater();
View customView = myinflater.inflate(R.layout.yourCustomeViewLayout, null);
actionBarContainer.addView(customView);
I found this workaround based on #Sean answer:
//This is for Jelly, ICS, Honeycomb
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){
LayoutInflater.from(this).inflate(resContent, (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);}
//This is for KitKat and Jelly 4.3
else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){
LayoutInflater.from(this).inflate(resContent, (ViewGroup) (((ViewGroup) wrapperView.getChildAt(0)).getChildAt(0)), true);}
//This is for Ginger
else{
LayoutInflater.from(this).inflate(resContent, (ViewGroup) ((LinearLayout)((FrameLayout) wrapperView.getChildAt(0)).getChildAt(0)).getChildAt(1), true);}
I found a much simpler way to do this.
I just applied android:translationZ="10dp" to the view which I need to be covering the action bar.
I chose 10dp but it can actually be anything you want as long as it is superior to the actionbar's elevation
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:translationZ="10dp"
android:src="#drawable/potatoe" />
Also, don't worry about Android studio's following warning :
"translationZ can't be used with API<21".
It will be ignored, but you don't really care because the toolbar shouldn't cover your view with APIs inferior to 21.
Try using ActionBar.setCustomView(). That's the only way to change the appearance of that area of the screen. You can't stick a View into the area "above" the ActionBar, because that area is basically controlled by the system. On the other hand, you can provide your own layout for it.
If you explain in more detail what you're trying to do, respondents might have some better design ideas.
https://github.com/michaelye/EasyDialogDemo
see the demo above,it may help you
dialog.setLocation(new location[])//point in screen
you could set the location[] yourself.
Use the android:actionLayout in your menu.xml file.
<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_id"
android:title="#string/menu_string_to_show"
android:icon="#drawable/ic_menu_icon_name"
android:showAsAction="always"
android:actionLayout="#layout/action_button_foo" /></menu>
Then create your action_button_foo.xml layout:
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/menu_string_to_show"
android:drawableLeft="#drawable/ic_menu_icon_name"
android:background="#drawable/bg_btn_action_bar"
android:clickable="true" />
To handle click do the following:
#Overridepublic boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
final MenuItem item = menu.findItem(R.id.menu_id);
item.getActionView().setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(item);
}
});
return super.onCreateOptionsMenu(menu);}
That's if :)
(Reference: http://www.vogella.com/articles/AndroidActionBar/article.html)Custom Views in the ActionBar
You can also add a custom View to the ActionBar. For this you use the setCustomView method for the ActionView class. You also have to enable the display of custom views via the setDisplayOptions() method by passing in the ActionBar.DISPLAY_SHOW_CUSTOM flag.
For example you can define a layout file which contains a EditText element.
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/searchfield"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textFilter" >
This layout can be assigned to the ActionBar via the following code. The example code allow attaches a listener to the custom view.
package com.vogella.android.actionbar.customviews;
import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
search.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
Toast.makeText(MainActivity.this, "Search triggered",
Toast.LENGTH_LONG).show();
return false;
}
});
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
}
}
The explanations here are all too long:
Wrap your main layout file into a top level ViewGroup (e.g. wrap a CoordinatorLayout into a FrameLayout), then inject or declare the view in the new top level layout out. The view will appear above the action bar.

Android - adding different views(widgets) to the screen without using a layout?

I am preparing to do an android demonstration of sorts and one of the first apps that i would like to write would be a screen filled with different widgets(which of course are views) but would like to put them on the screen without any layout built to hold them. is this possible or do you have to use a layout to put more than one view(widget) on the screen at once?
So right now i can do something like:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
TextView view1 = new TextView(this);
view1.setText("I am view one");
setContentView(view1);
}
}
In this case i really havent specified a layout but there doesnt seem to be a way to position multiple widgets on the screen without setting a layout. The purpose of this would be to show why you would want to use layouts. perhaps there is a way to display widgets on the screen without having to call the setContentView method.
You can only add multiple widgets/views to something called a ViewGroup. If you take a look at the documentation you'll see - not surprisingly - that basically all layouts extend this class. Similarly, if you look up the documentation on e.g. a TextView, you'll find that it doesn't extend ViewGroup (it does inherit from View, just like ViewGroup, which means it's on a different branch in the hierarchy tree).
In other words: you will need some sort of a layout in order to display more than a single widget/view at a time. You will also always need an explicit call to setContentView(), unless you use something like a ListActivity or ListFragment that by default creates a layout with a ListView as root.
That being said, your example is actually just a programmatical way of setting the following layout on the activity:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:text="I am view one" />
You can do it like this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frameLayout = new FrameLayout(this);
TextView view1 = new TextView(this);
view1.setText("I am view one");
frameLayout.addView(view1);
// add more widgets into ViewGroup as you want
// then set the viewgroup as content view
setContentView(frameLayout);
}

Adding a button to the android emulator skin

I'm trying to add a button to one of the default emulator skins. I used the layout file to get the button to appear but I'm not sure how to map it so that it actually does something.
You want to grab the button from the layout XML with something like this in onCreate:
Button xButton = (Button)findViewById(R.id.buttonX); //buttonX is the id you gave the button in the layout
Then you could set a click listener for that button in your onCreate like this:
xButton.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// do stuff here
}});
Very late but here is what I've found:
Create your skin as normal with the button images in place (rendered)
Create a button overlay image which is going to be drawn over the button when you mouse move over it with the mouse (can be the same for all buttons given it is only meant to be a focus indicator)
In your skin define the button(s) in the layout (see below)
For each button you can link it to a specific qemu code (see https://android.googlesource.com/platform/external/qemu.git/+/8b9887163ce94928aec159956d1a61fc93bb949d/android/skin/file.c#122)
layout:
parts {
device {
...
}
portrait {
...
buttons {
search { // see qemu codes
image xxxx.png // the overlay image to show on mouse move over
x 00000 // the top-left coordinate to show the image
y 00000 //
}
}
}
}
PS: I am pretty sure the button size is dependant on the button image dimensions.

Categories

Resources