I am using a custom InfoWindow in my app. I have two question related to it.
Is it possible to make multiline snippet in InfoWindow
Say am adding some data lets say I need to show LATTITUDE and LONGITUDE when I click on marker. Normally if u set these values in snippet they appear on same line. I would like to show them on two line. Is that possible
I googled about multiline snippet and couldn't find anything much useful so came up with the idea of customising InfoWindow.
2.Below show is my custom InfoWindow which gives me NullPointerException
Getting exception from try-catch loop. I followed some code I found while googleing but it's not working.
private class MyCustomInfoWindow implements InfoWindowAdapter{
private View view;
public MyCustomInfoWindow(){
}
#Override
public View getInfoContents(Marker markr) {
// TODO Auto-generated method stub
return null;
}
#Override
public View getInfoWindow(Marker marker) {
// TODO Auto-generated method stub
view = getLayoutInflater().inflate(R.layout.mycustom_infowindow, null);
TextView marker_heading = (TextView)findViewById(R.id.marker_heading);
try{
String m_heading = marker.getId();
marker_heading.setText(m_heading);
}
catch(Exception exx){
Toast.makeText(getApplicationContext(), "getInfoWindow Error is " + marker_heading.length(), Toast.LENGTH_LONG).show();
}
return view;
}
}
My custom
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/marker_heading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:typeface="serif"
android:textStyle="bold"
/>
</LinearLayout>
Using Google Maps V2
Could someone please tell me where am going wrong .
Use
TextView marker_heading = (TextView)view.findViewById(R.id.marker_heading);
to initialize marker_heading TextView instance because TextView is inside mycustom_infowindow layout
You should replace this
TextView marker_heading = (TextView)findViewById(R.id.marker_heading);
With
TextView marker_heading = (TextView)view.findViewById(R.id.marker_heading);
Use
TextView marker_heading = (TextView)view.findViewById(R.id.marker_heading);
you have to pass your View's object as a refernce to find id for TextView
Related
I use a customized info window so that I can achieve a gray background and white text color. Yet, I get a white frame around it. I want all of the Info Window to be gray, that is including its triangular edge that points to the spot.
I use this code in my Activity:
map.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override // Use default InfoWindow frame
public View getInfoWindow(Marker marker) { return null; }
#Override // Defines the contents of the InfoWindow
public View getInfoContents(Marker marker) {
View v = getLayoutInflater().inflate(R.layout.map_info_window, null);
TextView tv_location = (TextView) v.findViewById(R.id.tv_location);
tv_location.setText(marker.getTitle());
return v;
}});
and this is my layout:
<!--?xml version="1.0" encoding="utf-8"?-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map_info_window"
android:layout_width="match_parent"
android:background="#color/light_grey"
android:orientation="horizontal"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tv_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white" />
</LinearLayout>
You have to override the getInfoWindow () method and inflate you custom layout in that function.
From Documentation
public abstract View getInfoWindow (Marker marker)
Provides a custom info window for a marker. If this method returns a
view, it is used for the entire info window. If you change this view
after this method is called, those changes will not necessarily be
reflected in the rendered info window. If this method returns null ,
the default info window frame will be used, with contents provided by
getInfoContents(Marker).
#Override // Use default InfoWindow frame
public View getInfoWindow (Marker marker){
View v = getLayoutInflater().inflate(R.layout.map_info_window, null);
TextView tv_location = (TextView) v.findViewById(R.id.tv_location);
tv_location.setText(marker.getTitle());
return v;
}
#Override // Defines the contents of the InfoWindow
public View getInfoContents (Marker marker){
// TODO Auto-generated method stub
return null;
}
So i think you should reverse your function implementation.
I am Working on an android application project which requires to show Google Map InfoWindow background to be transparent.
But I am not able to do it even after making layout for InfoWindow transparent it always show the default white pointer background.
Please suggest a solution, how to solve this problem?
I would like to recommend creating a custom XML file for your InfoWindow.
Create a custom XML file (eg. windowlayout.xml)
Add:
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(final Marker arg0) {
View v = getLayoutInflater().inflate(R.layout.windowlayout, null);
TextView address = (TextView) v.findViewById(R.id.tv_address);
address.setText("Address: "+sAddress);
TextView contact = (TextView) v.findViewById(R.id.tv_contact);
info.setText("Contact Number: "+sContactNumber);
return v;
}
});
You can make background transparent for this custom layout.
(I could not format the whole code, but the whole snippet is complete method)
I know that this question might be a duplicate of another question but i tried to follow what was suggested in solutions to similar questions without any success. I am relatively new to android so please kindly point me in the right direction.
Scenario:
I have a list view that has a custom layout file containing a small image and a text view. The list view displays all items as intended but what I want to do is as follows:
When a button is clicked, a condition is evaluated and if the result is true, i want to change the default image to another one. I am aware that I have to perform the image switching in the get view method that I have to override.
public View getView(int position, View convertView, ViewGroup parent) {
View itemView=convertView;
if (itemView==null) {
itemView=getLayoutInflater().inflate(R.layout.check_list_view, parent, false);
}
MailObject currentMailObject=mailList.get(position);
ImageView ivCurrentMail=(ImageView)itemView.findViewById(R.id.ivMailIcon);
if (mailList.get(position).isScanned()) {
ivCurrentMail.setImageResource(R.drawable.ic_mail_scanned);
}
return itemView;
}
The code for the button is:
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), scanResult, Toast.LENGTH_LONG).show();
if(!scannedMails.contains(scanResult))
{
scannedMails.add(scanResult);
for (int i = 0; i < mailList.size(); i++) {
if (mailList.get(i).getCode().equalsIgnoreCase(scanResult)) {
int position=i;
mailList.get(i).setScanned(true);
ImageView ivCurrent = (ImageView) lvMails.getAdapter().getView(position, null, null).findViewById(R.id.ivMailIcon);
ivCurrent.setImageResource(R.drawable.ic_mail_scanned);
lvMails.invalidateViews();
}
}
}
}
});
The XML file for a list view item is as follows:
<ImageView
android:id="#+id/ivMailIcon"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="#drawable/ic_mail_not_scanned" />
<TextView
android:id="#+id/tvMailItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="17dp"
android:layout_toRightOf="#+id/ivMailIcon"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
I did test if the condition evaluates as it should by displaying a Toast message on list view item click and the results were positive but the image just does not change. Please let me know where I went wrong or missed something. Thanks
You're setting the same image twice. In both cases, you use the setImageResource() method for the ImageView that points to R.id.ivMailIcon to set the drawable as R.drawable.ic_mail_scanned.
You are probably "setting" to image again correctly on a click, but since it's the same image, it won't appear to change.
I have a problem with marker on google maps api v2.
I would like to customize infoWindows with a WebView:
Here my code of InfoWindowAdapter
mMap.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker arg0) {
View v = getLayoutInflater().inflate(R.layout.info_window_layout, null);
TextView title = (TextView) v.findViewById(R.id.title_marker);
WebView snippet = (WebView) v.findViewById(R.id.item_snippet);
title.setText(arg0.getTitle());
snippet.setVisibility(WebView.VISIBLE);
snippet.loadData(arg0.getSnippet(),"text/html", "UTF-8");
return v;
}
});
And this is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/title_marker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<WebView
android:id="#+id/item_snippet"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
My problem is that I see the content into the TextView, but not the content into the WebView.
What i'm doing wrong?
Thanks a lot
You can't use a WebView directly. The reason is (source: official docs):
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.
You can try drawing the webview on a bitmap (after the content has been loaded) and supplying an ImageView with that bitmap in the InfoWindow adapter, but you will lose interactivity with the webview anyway.
after a lot of tests, googling and some reversing I can say that view you return in getInfoContents is used to render into a Bitmap and then hidden. The bitmap is then displayed via GL
I've found a workaround that can be fine for you.
private View mGhost;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mGhost = new View(this);
mGhost.setLayoutParams(new LayoutParams(0, 0));
mGhost.setVisibility(View.GONE);
....
}
public void onMapReady(GoogleMap map) // or whatever
{
map.setInfoWindowAdapter(new InfoWindowAdapter()
{
#Override
public View getInfoWindow(Marker marker)
{
return null;
}
#Override
public View getInfoContents(final Marker marker)
{
WebView webview = new WebView(MainActivity.this);
webview.loadUrl(marker.getSnippet());
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
AlertDialog alert = builder.setView(webview).create();
alert.show();
alert.getWindow().setLayout(200, 200);
mGhost.post(new Runnable()
{
#Override
public void run()
{
marker.hideInfoWindow();
}
});
return mGhost;
}
});
}
in this example I've used the snippet to store the url, It's not exactly what did you asked, but it may look similar.
Edit: the first version was recycling the WebView but it's not possible without some trick to remove it from the Alert, this revised version doesn't shows the InfoContents box below but has still an issue, when pressed it keeps a sort of state, and it believes the marker is clicked after closing the dialog.
You may use a layout that contains a WebView to decor a bit the window
Edit2: Reverted to something like the first version, a blank InfoContents box shows for bit I'm not sure it's avoidable.
I have Listview with editext and textview.
When i touch on edittext then edittext lost focus!
I resolved this problem by setting android:windowSoftInputMode="adjustPan"(AndroidManifest.xml).
Now i touch on edittext than editext get focus but application label and some raw of listview disappear(top part).
I want to get focus when user touch on edittext without loss application label and some raw of listview.
Code that i have implemented :
Below coding get focus when user touch on edittext but application label and some raw of listview disappear when soft keypad pop up.I want to get focus when user touch on edittext without loss application label and some raw of listview.
1)AndroidManifest.xml
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".MyListViewDemoActivity"
android:label="#string/app_name"
android:windowSoftInputMode="adjustPan"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
2) raw_layout.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText android:id="#+id/mEditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
3) main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<ListView android:id="#+id/mListView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
4) MyListViewDemoActivity
public class MyListViewDemoActivity extends Activity {
private ListView mListView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mListView=(ListView)findViewById(R.id.mListView);
mListView.setAdapter(new MyAdapter(this));
}
}
class MyAdapter extends BaseAdapter {
private Activity mContext;
private String character[]={"a","b","c","d","e","f","g","h","i","j"};
public MyAdapter(Activity context)
{
mContext=context;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return character.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
private class Holder
{
EditText mEditText;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final Holder holder;
if (convertView == null) {
holder = new Holder();
LayoutInflater inflater =mContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.raw_layout, null);
holder.mEditText = (EditText) convertView
.findViewById(R.id.mEditText);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.mEditText.setText(character[position]);
holder.mEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// TODO Auto-generated method stub
if (!hasFocus){
final EditText etxt = (EditText) v;
holder.mEditText.setText(etxt.getText().toString());
}
}
});
return convertView;
}
}
I was having the same problem. My numberic keyboard would momentarily appear before being replaced by the qwerty keyboard and the EditText losing focus.
The problem is that the keyboard appearing makes your EditText lose focus. To prevent this put the following in your AndroidManifest.xml for the appropriate Activity (or Activities):
android:windowSoftInputMode="adjustPan"
See Android documentation:
When the input method appears on the screen, it reduces the amount of space available for your app's UI. The system makes a decision as to how it should adjust the visible portion of your UI, but it might not get it right. To ensure the best behavior for your app, you should specify how you'd like the system to display your UI in the remaining space.
To declare your preferred treatment in an activity, use the android:windowSoftInputMode attribute in your manifest's <activity> element with one of the "adjust" values.
For example, to ensure that the system resizes your layout to the available space—which ensures that all of your layout content is accessible (even though it probably requires scrolling)—use "adjustResize"
Without seeing your code, how can we suggest the possible solution for your problem. So keep practice of posting possible code whenever you ask any question.
However, here i have found one tutorial for implementing Android Focusable EditText inside ListView. Go through the example and try to implement in your way or find out the solution for your problem.
I solved this "Putting EditText in ListView as an item" problem recently. I am not very good at English. So if there's something I don't explain clearly please tell me.
We know ListView can be scrolled verticaly and we want to put EditText in ListView as an item.
First:
Add
android:windowSoftInputMode="adjustResize"
in your AndroidManifest.xml at the activity node.
Second:
We create an pojo as model data source to control EditText state
Line.java
public class Line{
int num;
String text;
boolean focus;
get set method and so on...
}
Third:
We write an adapter to adapt EditText to ListView.
Item item_line.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="80dp">
<EditText
android:id="#+id/etLine"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
</FrameLayout>
Adapter:
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_line, parent, false);
holder.etLine = (EditText) convertView.findViewById(R.id.etLine);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final Line line = lines.get(position);
// step 1: remove android.text.TextWatcher added in step 5 to make sure android.text.TextWatcher
// don't trigger in step 2;
// why?
//
// note: When an object of a type is attached to an Editable,
// TextWatcher's methods will be called when the EidtText's text is changed.
//
// EditText use a ArrayList<TextWatcher> type object to store the listener, so we must
// make sure there's only one TextWatcher object in this list;
//
// Avoid triggering TextWatcher's method in step 2 we remove it at first time.
//
if (holder.etLine.getTag() instanceof TextWatcher) {
holder.etLine.removeTextChangedListener((TextWatcher) (holder.etLine.getTag()));
}
// step 2: set text and focus after remove android.text.TextWatcher(step 1);
holder.etLine.setHint(position + ".");
// set text
if (TextUtils.isEmpty(line.getText())) {
holder.etLine.setTextKeepState("");
} else {
holder.etLine.setTextKeepState(line.getText());
}
// set focus status
// why?
//
// note: ListView has a very elegant recycle algorithm. So views in ListView is not reliable.
// Especially in this case, EditText is an item of ListView. Software input window may cause
// ListView relayout leading adapter's getView() invoke many times.
// Above all if we change EditText's focus state directly in EditText level(not in Adapter).
// The focus state may be messed up when the particularly view reused in other position.
//
// So using data source control View's state is the core to deal with this problem.
if (line.isFocus()) {
holder.etLine.requestFocus();
} else {
holder.etLine.clearFocus();
}
// step 3: set an OnTouchListener to EditText to update focus status indicator in data source
// why?
//
// in step 2, we know we must control view state through data source. We use OnTouchListener
// to watch the state change and update the data source when user move up fingers(ACTION_UP).
// We don't want to consume the touch event, simply return false in method onTouch().
holder.etLine.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
check(position);
}
return false;
}
});
// step 4: set TextWatcher to EditText to listen text changes in EditText to updating the text in data source
// why?
//
// again, use data source to control view state.
// When user edit the text in one EditText item and scroll the ListView. The particularly EditText item will be
// reuse in adapter's getView(), this may lead text messed up in ListView.
// How to deal with this problem?
// Easy! We update the text in data source at the same time when user is editing. TextWatcher is the best way to
// do this.
final TextWatcher watcher = new SimpeTextWather() {
#Override
public void afterTextChanged(Editable s) {
if (TextUtils.isEmpty(s)) {
line.setText(null);
} else {
line.setText(String.valueOf(s));
}
}
};
holder.etLine.addTextChangedListener(watcher);
// step 5: Set watcher as a tag of EditText.
// so we can remove the same object which was setted to EditText in step 4;
// Make sure only one callback is attached to EditText
holder.etLine.setTag(watcher);
return convertView;
}
/**
* change focus status in data source
*/
private void check(int position) {
for (Line l : lines) {
l.setFocus(false);
}
lines.get(position).setFocus(true);
}
static class ViewHolder {
EditText etLine;
}
All done!
You can read more details in my github.
Demo: https://github.com/Aspsine/EditTextInListView
ListView recreate the View,
Try to use a LinearLayout inside in ScrollView, then in your code use a runOnUiThread to fill your view in an other thread like this
public void fillDataTask(Context context, final LinearLayout listView) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
fillView(context, listView);
}
});
}
private void fillView(Context context, LinearLayout listView) {
MyAdapter adapter = new MyAdapter(context);
final int adapterCount = adapter.getCount();
for (int i = 0; i < adapterCount; i++) {
View item = adapter.getView(i, null, null);
listView.addView(item);
}
}
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:drawSelectorOnTop="false"
android:id="#+id/list1"
android:layout_weight="1"
android:cacheColorHint="#00000000"
android:focusable="false"
>
</ListView>