J'ai l'un des nouveaux MapFragment
s dans un ScrollView
. En fait, c'est un SupportMapFragment
, mais de toute façon. Cela fonctionne, mais il y a deux problèmes:
Lorsqu'il défile, il laisse un masque noir derrière. Le noir couvre exactement la zone où se trouvait la carte, à l'exception d'un trou où se trouvaient les boutons de zoom +/-. Voir capture d'écran ci-dessous. C'est sur Android 4.0.
La vue n'utilise pas requestDisallowInterceptTouchEvent()
lorsque l'utilisateur interagit avec la carte pour empêcher les touches d'interception de ScrollView
, donc si vous essayez de vous déplacer verticalement dans la carte, elle fait simplement défiler le contenant ScrollView
. Je pourrais théoriquement dériver une classe de vue MapView
et ajouter cette fonctionnalité, mais comment puis-je demander à MapFragment
d'utiliser mon MapView
personnalisé au lieu de celui standard?
L'application d'une image transparente sur le fragment mapview semble résoudre le problème. Ce n'est pas le plus joli, mais ça semble marcher. Voici un extrait XML qui montre ceci:
<RelativeLayout
Android:id="@+id/relativeLayout1"
Android:layout_width="match_parent"
Android:layout_height="300dp" >
<fragment
Android:id="@+id/map"
Android:name="com.google.Android.gms.maps.MapFragment"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"/>
<ImageView
Android:id="@+id/imageView123"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:src="@drawable/temp_transparent" />
</RelativeLayout>
Pour moi, l'ajout d'une ImageView transparente n'a pas aidé à supprimer complètement le masque noir. Les parties supérieure et inférieure de la carte montraient toujours le masque noir lors du défilement.
Donc, la solution, j'ai trouvé dans cette réponse avec un petit changement. J'ai ajouté,
Android:layout_marginTop="-100dp"
Android:layout_marginBottom="-100dp"
à mon fragment de carte car il était scrollview vertical. Donc, ma disposition ressemblait maintenant à ceci:
<RelativeLayout
Android:id="@+id/map_layout"
Android:layout_width="match_parent"
Android:layout_height="300dp">
<fragment
Android:id="@+id/mapview"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginTop="-100dp"
Android:layout_marginBottom="-100dp"
Android:name="com.google.Android.gms.maps.MapFragment"/>
<ImageView
Android:id="@+id/transparent_image"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:src="@color/transparent" />
</RelativeLayout>
Pour résoudre la deuxième partie de la question, j'ai défini requestDisallowInterceptTouchEvent(true)
pour mon ScrollView principal. Lorsque l'utilisateur a touché l'image transparente et s'est déplacé, j'ai désactivé le toucher sur l'image transparente pour MotionEvent.ACTION_DOWN
Et MotionEvent.ACTION_MOVE
Afin que le fragment de carte puisse prendre des événements tactiles.
ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scrollview);
ImageView transparentImageView = (ImageView) findViewById(R.id.transparent_image);
transparentImageView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
mainScrollView.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
mainScrollView.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
mainScrollView.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
Cela a fonctionné pour moi. J'espère que cela vous aide ..
Cela a probablement ses racines au même endroit et provoque le problème dans cette question . La solution consiste à utiliser un cadre transparent, qui est un peu plus léger qu'une image transparente.
Fait après beaucoup de R&D:
fragment_one.xml devrait ressembler à:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:id="@+id/scrollViewParent"
Android:orientation="vertical" >
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical" >
<RelativeLayout
Android:layout_width="match_parent"
Android:layout_height="400dip" >
<com.google.Android.gms.maps.MapView
Android:id="@+id/mapView"
Android:layout_width="match_parent"
Android:layout_height="match_parent" />
<View
Android:id="@+id/customView"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:background="@Android:color/transparent" />
</RelativeLayout>
<!-- Your other elements are here -->
</LinearLayout>
</ScrollView>
Votre Java de FragmentOne.Java ressemble à:
private GoogleMap mMap;
private MapView mapView;
private UiSettings mUiSettings;
private View customView
onCreateView
mapView = (MapView) rootView.findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
if (mapView != null) {
mMap = mapView.getMap();
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
mUiSettings = mMap.getUiSettings();
mMap.setMyLocationEnabled(true);
mUiSettings.setCompassEnabled(true);
mUiSettings.setMyLocationButtonEnabled(false);
}
scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent);
customView = (View)rootView.findViewById(R.id.customView);
customView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
scrollViewParent.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
scrollViewParent.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
scrollViewParent.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
J'ai utilisé ces structures et j'ai surmonté le problème.
J'ai utilisé une vue conteneur pour le fragment de cartes.
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<LinearLayout
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<TextView
Android:text="Another elements in scroll view1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
<com.erolsoftware.views.MyMapFragmentContainer
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="250dp">
<fragment
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"
Android:id="@+id/eventMap"
tools:context="com.erolsoftware.eventapp.EventDetails"
Android:name="com.google.Android.gms.maps.SupportMapFragment"/>
</com.erolsoftware.views.MyMapFragmentContainer>
<TextView
Android:text="Another elements in scroll view2"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
La classe de conteneur:
public class MyMapFragmentContainer extends LinearLayout {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN)
{
ViewParent p = getParent();
if (p != null)
p.requestDisallowInterceptTouchEvent(true);
}
return false;
}
public MyMapFragmentContainer(Context context) {
super(context);
}
public MyMapFragmentContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyMapFragmentContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
Pas besoin de lutter avec customScrollViews et des fichiers de mise en page transparents. utilisez simplement une version plus légère de google map et votre problème sera résolu.
map:liteMode="true"
ajoutez la propriété ci-dessus à l'intérieur du fragment de carte dans votre fichier de mise en page. et le problème sera résolu.
<ScrollView
Android:layout_width="match_parent"
::
::
::
<FrameLayout
Android:id="@+id/map_add_business_one_rl"
Android:layout_width="match_parent"
Android:layout_height="100dp"
>
<fragment
Android:id="@+id/map"
Android:name="com.google.Android.gms.maps.SupportMapFragment"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginTop="-100dp"
Android:layout_marginBottom="-100dp"
/>
</FrameLayout>
::
::
::
</ScrollView>
Pour la deuxième partie de la question - vous pouvez dériver une classe de fragments de SupportMapFragment et l'utiliser à la place dans votre mise en page. Vous pouvez ensuite remplacer Fragment # onCreateView , et y instancier votre MapView personnalisé.
Si cela ne fonctionne pas, vous pouvez toujours créer votre propre fragment - il vous suffit alors de prendre soin d'appeler vous-même toutes les méthodes du cycle de vie (onCreate, onResume, etc.). Cette réponse a plus de détails.