Google 地图 flicker/blink 黑色切换内容可见性
Google maps flicker/blink black on toggling content visibility
我已经在两个地方用 实现了我的地图片段:
- (主要)
--> (容器)
--> (片段膨胀) --> --> (容器)
--> (片段膨胀) --> --> (容器)
--> (地图片段膨胀) --> <片段>
- (主要)
--> (容器)
--> (片段膨胀) --> (容器)
--> (地图片段膨胀) --> <片段>
问题 是,在第一种情况下,当我单击地图标记或单击 ImageView 时,我的地图会闪烁从我的地图片段 ViewGroup 中,除了在 GONE 和 VISIBLE 之间切换图标可见性之外什么都不做。第二种情况工作正常。它给了我一个提示,地图的闪烁是由于其他视图改变了它们在 NestedScrollView 中的可见性。可能也是因为家长太多了。
我尝试实施 android:layerType="hardware"
但它没有帮助。此外,当可见性在 VISIBLE 和 INVISIBLE 之间切换时,一切正常,但这不是解决方案。
我已经记录了被告知地图的行为并附上了它here。在记录中,我单击 ToggleButton 并在 GONE 和 VISIBLE 之间切换一个小勾图标。
有什么解决办法吗?
代码
主要 Activity
这是一个导航抽屉 Activity
public class MainActivityC extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_c);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_c, menu);
return true;
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
片段 1
此片段包含 ViewPager2
public class GalleryFragment extends Fragment{
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_gallery, container, false);
}
private Context context;
private ViewPager2 viewPager2;
private TabLayout tabLayout;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
context = getActivity();
initTab();
}
private void initTab() {
viewPager2 = getView().findViewById(R.id.viewpager2_walks_saved);
viewPager2.setAdapter(new WalksSavedPagerAdapter(getActivity()));
viewPager2.setUserInputEnabled(false); // NO SCROLL
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
switch (position) {
case 0:
String text1 = "Walks History";
((MainActivityC) context).getSupportActionBar().setTitle(text1);
break;
case 1:
String text2 = "Walks Statistics";
((MainActivityC) context).getSupportActionBar().setTitle(text2);
break;
}
}
});
tabLayout = getView().findViewById(R.id.tabLayout_walks_statistics);
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
switch (position) {
case 0:
tab.setText("Walks History");
break;
case 1:
tab.setText("Walks Statistics");
break;
}
}
}
);
tabLayoutMediator.attach();
}
}
布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="?attr/colorPrimary">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap"
android:elevation="4dp">
<TextView
android:id="@+id/drawer_fragment_saved_walks_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Saved Walks"
android:textSize="30sp"
android:textColor="@color/white"
android:layout_gravity="center"/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="0dp"
android:layout_width="match_parent"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
<!--android:layout_height="?attr/actionBarSize"-->
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- Tab to chose between Saved Walks and Statistics -->
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout_walks_statistics"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:layout_gravity="bottom"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
app:tabPaddingBottom="4dp"
app:tabPaddingTop="4dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2_walks_saved"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
片段 2
此片段显示在 ViewPager2 中并具有自己的 ViewPager2
public class StatisticsFragment extends Fragment {
private ViewPager2 viewPager2;
private TabLayout tabLayoutViewPager;
private StatisticsPagerAdapter statisticsPagerAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_walks_statistics, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
init();
}
private void init(){
statisticsPagerAdapter = new StatisticsPagerAdapter(getActivity());
viewPager2 = getView().findViewById(R.id.viewpager2_statistics);
viewPager2.setAdapter(statisticsPagerAdapter);
viewPager2.setUserInputEnabled(false); // NO SCROLL
tabLayoutViewPager = getView().findViewById(R.id.tabLayout_statistics);
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
tabLayoutViewPager, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
switch (position) {
case 0:
tab.setText("Events");
break;
case 1:
tab.setText("Chronology");
break;
case 2:
tab.setText("Heat Map");
break;
}
}
}
);
tabLayoutMediator.attach();
}
}
布局:
<androidx.core.widget.NestedScrollView
android:id="@+id/heatmap_nested_scroll_view"
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"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout_statistics"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@android:color/transparent"
android:layout_marginTop="8dp"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
app:tabPaddingBottom="4dp"
app:tabPaddingTop="4dp" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@android:color/darker_gray" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2_statistics"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
使用 GoogleMap 的片段 3
此片段显示在 ViewPager2 中并包含闪烁的地图
public class StatisticsHeatmapFragment extends Fragment implements OnMapReadyCallback,
CompoundButton.OnCheckedChangeListener {
private Context context;
private Fragment parentFragment;
private ToggleButton iconRescale;
private ImageView iconCheck;
private MapFragment mapFragment;
private GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_statistics_heatmap, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initiate();
}
@SuppressLint("ClickableViewAccessibility") // Due to the touch listener
private void initiate() {
context = getActivity();
// A neat way to find the parent fragment in a child ViewPager fragment
List<Fragment> fragment = getActivity().getSupportFragmentManager().getFragments();
for (Fragment f:fragment) {
if (f instanceof StatisticsFragment){
parentFragment = f;
}
}
ImageView transparentImageView = (ImageView) getView().findViewById(R.id.heatmap_transparent_image);
// Tag is automatically given by ViewPager2 like "f" + position, but I have overwritten it.
// So the StatisticsFragment is "f101". There the NestedScrollView locates.
final NestedScrollView nestedScrollView = (NestedScrollView)
getActivity().getSupportFragmentManager().findFragmentByTag("f101").getView();
// The warning comes up because Android wants to remind you to think about the blind or visually impaired people who may be using your app
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.
nestedScrollView.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
nestedScrollView.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
nestedScrollView.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
mapFragment = (MapFragment) getActivity().getFragmentManager()
.findFragmentById(R.id.map_statistics);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
initToggleButtons();
}
private void initToggleButtons() {
iconCheck = getView().findViewById(R.id.icon_check_heatmap_stats);
iconRescale = getView().findViewById(R.id.icon_rezoom_heatmap_stats);
iconRescale.setChecked(true);
iconRescale.setOnCheckedChangeListener(this);
}
/**
* CheckChange listener for events icon (ToggleButton)
*/
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.equals(iconRescale)){
if (isChecked) {
DrawableCompat.setTint(
DrawableCompat.wrap(iconRescale.getBackground()),
ContextCompat.getColor(context, R.color.black));
iconCheck.setVisibility(View.VISIBLE);
Toast.makeText(context, "Map scale to the data is ON", Toast.LENGTH_SHORT).show();
} else {
DrawableCompat.setTint(
DrawableCompat.wrap(iconRescale.getBackground()),
ContextCompat.getColor(context, R.color.common_google_signin_btn_text_light));
iconCheck.setVisibility(View.GONE);
Toast.makeText(context, "Map scale to the data is OFF", Toast.LENGTH_SHORT).show();
}
}
}
}
布局:
<FrameLayout 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">
<fragment
xmlns:map="http://schemas.android.com/apk/res-auto"
android:name="com.google.android.gms.maps.MapFragment"
android:id="@+id/map_statistics"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:mapType="normal" />
<ImageView
android:id="@+id/heatmap_transparent_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@android:color/transparent" />
<ImageView
android:id="@+id/icon_check_heatmap_stats"
android:layout_width="14dp"
android:layout_height="14dp"
android:background="@drawable/ic_baseline_check_24"
android:backgroundTint="@android:color/holo_red_light"
android:layout_gravity="end|top"
android:layout_marginTop="28dp"
android:layout_marginEnd="69dp"/>
<ToggleButton
android:id="@+id/icon_rezoom_heatmap_stats"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/ic_baseline_zoom_out_map_24"
android:backgroundTint="@color/black"
android:layout_gravity="end|top"
android:layout_marginTop="20dp"
android:layout_marginEnd="60dp"
android:textOn=" "
android:textOff=" "/>
</FrameLayout>
P.S。使用此代码需要多次单击图标才能发现问题。
我已经解决了我自己的问题,但是我们非常欢迎其他解决方案。
问题在于地图的父级 <NestedScrollView>
具有 android:fillViewport="true"
属性,这会强制视图拉伸其内容以填充视口。
解决方法是将地图的视图设置为恒定高度。因此,例如 android:layout_height="match_parent"
应更改为 android:layout_height="500dp"
。另外,高度可以根据需要动态设置。
加法
Google NestedScrollView
中的地图视图可以保留 android:layout_height="match_parent"
。然后,要固定视图的高度(这是避免闪烁所必需的),请分别在 onCreate
或 onCreateView
或 Activity
或 Fragment
中添加此代码段:
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int height = v.getHeight();
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height;
view.setLayoutParams(params);
view.removeOnLayoutChangeListener(this);
}
});
我已经在两个地方用
- (主要)
--> (容器)
--> (片段膨胀)--> --> (容器)
--> (片段膨胀)--> --> (容器)
--> (地图片段膨胀)--> <片段> - (主要)
--> (容器)
--> (片段膨胀)--> (容器)
--> (地图片段膨胀)--> <片段>
问题 是,在第一种情况下,当我单击地图标记或单击 ImageView 时,我的地图会闪烁从我的地图片段 ViewGroup 中,除了在 GONE 和 VISIBLE 之间切换图标可见性之外什么都不做。第二种情况工作正常。它给了我一个提示,地图的闪烁是由于其他视图改变了它们在 NestedScrollView 中的可见性。可能也是因为家长太多了。
我尝试实施 android:layerType="hardware"
但它没有帮助。此外,当可见性在 VISIBLE 和 INVISIBLE 之间切换时,一切正常,但这不是解决方案。
我已经记录了被告知地图的行为并附上了它here。在记录中,我单击 ToggleButton 并在 GONE 和 VISIBLE 之间切换一个小勾图标。
有什么解决办法吗?
代码
主要 Activity
这是一个导航抽屉 Activitypublic class MainActivityC extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_c);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_c, menu);
return true;
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
片段 1
此片段包含 ViewPager2public class GalleryFragment extends Fragment{
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_gallery, container, false);
}
private Context context;
private ViewPager2 viewPager2;
private TabLayout tabLayout;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
context = getActivity();
initTab();
}
private void initTab() {
viewPager2 = getView().findViewById(R.id.viewpager2_walks_saved);
viewPager2.setAdapter(new WalksSavedPagerAdapter(getActivity()));
viewPager2.setUserInputEnabled(false); // NO SCROLL
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
switch (position) {
case 0:
String text1 = "Walks History";
((MainActivityC) context).getSupportActionBar().setTitle(text1);
break;
case 1:
String text2 = "Walks Statistics";
((MainActivityC) context).getSupportActionBar().setTitle(text2);
break;
}
}
});
tabLayout = getView().findViewById(R.id.tabLayout_walks_statistics);
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
switch (position) {
case 0:
tab.setText("Walks History");
break;
case 1:
tab.setText("Walks Statistics");
break;
}
}
}
);
tabLayoutMediator.attach();
}
}
布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="?attr/colorPrimary">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|snap"
android:elevation="4dp">
<TextView
android:id="@+id/drawer_fragment_saved_walks_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Saved Walks"
android:textSize="30sp"
android:textColor="@color/white"
android:layout_gravity="center"/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="0dp"
android:layout_width="match_parent"
app:layout_collapseMode="pin" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
<!--android:layout_height="?attr/actionBarSize"-->
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- Tab to chose between Saved Walks and Statistics -->
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout_walks_statistics"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:layout_gravity="bottom"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
app:tabPaddingBottom="4dp"
app:tabPaddingTop="4dp" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2_walks_saved"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
片段 2
此片段显示在 ViewPager2 中并具有自己的 ViewPager2public class StatisticsFragment extends Fragment {
private ViewPager2 viewPager2;
private TabLayout tabLayoutViewPager;
private StatisticsPagerAdapter statisticsPagerAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_walks_statistics, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
init();
}
private void init(){
statisticsPagerAdapter = new StatisticsPagerAdapter(getActivity());
viewPager2 = getView().findViewById(R.id.viewpager2_statistics);
viewPager2.setAdapter(statisticsPagerAdapter);
viewPager2.setUserInputEnabled(false); // NO SCROLL
tabLayoutViewPager = getView().findViewById(R.id.tabLayout_statistics);
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
tabLayoutViewPager, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
switch (position) {
case 0:
tab.setText("Events");
break;
case 1:
tab.setText("Chronology");
break;
case 2:
tab.setText("Heat Map");
break;
}
}
}
);
tabLayoutMediator.attach();
}
}
布局:
<androidx.core.widget.NestedScrollView
android:id="@+id/heatmap_nested_scroll_view"
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"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout_statistics"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@android:color/transparent"
android:layout_marginTop="8dp"
app:tabIndicatorHeight="3dp"
app:tabMode="fixed"
app:tabPaddingBottom="4dp"
app:tabPaddingTop="4dp" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@android:color/darker_gray" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager2_statistics"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
使用 GoogleMap 的片段 3
此片段显示在 ViewPager2 中并包含闪烁的地图public class StatisticsHeatmapFragment extends Fragment implements OnMapReadyCallback,
CompoundButton.OnCheckedChangeListener {
private Context context;
private Fragment parentFragment;
private ToggleButton iconRescale;
private ImageView iconCheck;
private MapFragment mapFragment;
private GoogleMap map;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_statistics_heatmap, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initiate();
}
@SuppressLint("ClickableViewAccessibility") // Due to the touch listener
private void initiate() {
context = getActivity();
// A neat way to find the parent fragment in a child ViewPager fragment
List<Fragment> fragment = getActivity().getSupportFragmentManager().getFragments();
for (Fragment f:fragment) {
if (f instanceof StatisticsFragment){
parentFragment = f;
}
}
ImageView transparentImageView = (ImageView) getView().findViewById(R.id.heatmap_transparent_image);
// Tag is automatically given by ViewPager2 like "f" + position, but I have overwritten it.
// So the StatisticsFragment is "f101". There the NestedScrollView locates.
final NestedScrollView nestedScrollView = (NestedScrollView)
getActivity().getSupportFragmentManager().findFragmentByTag("f101").getView();
// The warning comes up because Android wants to remind you to think about the blind or visually impaired people who may be using your app
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.
nestedScrollView.requestDisallowInterceptTouchEvent(true);
// Disable touch on transparent view
return false;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
nestedScrollView.requestDisallowInterceptTouchEvent(false);
return true;
case MotionEvent.ACTION_MOVE:
nestedScrollView.requestDisallowInterceptTouchEvent(true);
return false;
default:
return true;
}
}
});
mapFragment = (MapFragment) getActivity().getFragmentManager()
.findFragmentById(R.id.map_statistics);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
initToggleButtons();
}
private void initToggleButtons() {
iconCheck = getView().findViewById(R.id.icon_check_heatmap_stats);
iconRescale = getView().findViewById(R.id.icon_rezoom_heatmap_stats);
iconRescale.setChecked(true);
iconRescale.setOnCheckedChangeListener(this);
}
/**
* CheckChange listener for events icon (ToggleButton)
*/
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (buttonView.equals(iconRescale)){
if (isChecked) {
DrawableCompat.setTint(
DrawableCompat.wrap(iconRescale.getBackground()),
ContextCompat.getColor(context, R.color.black));
iconCheck.setVisibility(View.VISIBLE);
Toast.makeText(context, "Map scale to the data is ON", Toast.LENGTH_SHORT).show();
} else {
DrawableCompat.setTint(
DrawableCompat.wrap(iconRescale.getBackground()),
ContextCompat.getColor(context, R.color.common_google_signin_btn_text_light));
iconCheck.setVisibility(View.GONE);
Toast.makeText(context, "Map scale to the data is OFF", Toast.LENGTH_SHORT).show();
}
}
}
}
布局:
<FrameLayout 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">
<fragment
xmlns:map="http://schemas.android.com/apk/res-auto"
android:name="com.google.android.gms.maps.MapFragment"
android:id="@+id/map_statistics"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:mapType="normal" />
<ImageView
android:id="@+id/heatmap_transparent_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@android:color/transparent" />
<ImageView
android:id="@+id/icon_check_heatmap_stats"
android:layout_width="14dp"
android:layout_height="14dp"
android:background="@drawable/ic_baseline_check_24"
android:backgroundTint="@android:color/holo_red_light"
android:layout_gravity="end|top"
android:layout_marginTop="28dp"
android:layout_marginEnd="69dp"/>
<ToggleButton
android:id="@+id/icon_rezoom_heatmap_stats"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/ic_baseline_zoom_out_map_24"
android:backgroundTint="@color/black"
android:layout_gravity="end|top"
android:layout_marginTop="20dp"
android:layout_marginEnd="60dp"
android:textOn=" "
android:textOff=" "/>
</FrameLayout>
P.S。使用此代码需要多次单击图标才能发现问题。
我已经解决了我自己的问题,但是我们非常欢迎其他解决方案。
问题在于地图的父级 <NestedScrollView>
具有 android:fillViewport="true"
属性,这会强制视图拉伸其内容以填充视口。
解决方法是将地图的视图设置为恒定高度。因此,例如 android:layout_height="match_parent"
应更改为 android:layout_height="500dp"
。另外,高度可以根据需要动态设置。
加法
Google NestedScrollView
中的地图视图可以保留 android:layout_height="match_parent"
。然后,要固定视图的高度(这是避免闪烁所必需的),请分别在 onCreate
或 onCreateView
或 Activity
或 Fragment
中添加此代码段:
view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int height = v.getHeight();
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height;
view.setLayoutParams(params);
view.removeOnLayoutChangeListener(this);
}
});