如何将布局拆分为 3 个不同的滑动视图

Posted

技术标签:

【中文标题】如何将布局拆分为 3 个不同的滑动视图【英文标题】:How can I split my layout in 3 different swipe views 【发布时间】:2019-02-11 20:54:46 【问题描述】:

我已经构建了一个具有活动和以下布局的应用程序:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:fitsSystemWindows="true"
android:orientation="vertical" >

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:fitsSystemWindows="true"
android:orientation="vertical" >

<TextView
    android:id="@+id/textView"
    android:layout_
    android:layout_
    android:scrollbars="vertical"
    android:textSize="18sp" />

<com.jjoe64.graphview.GraphView
    android:id="@+id/graph"
    android:layout_
    android:layout_ />

<RelativeLayout
    android:layout_
    android:fitsSystemWindows="true"
    android:layout_ >

    <EditText
        android:id="@+id/editText"
        android:layout_
        android:layout_
        android:layout_alignBottom="@+id/send"
        android:layout_marginRight="80dp"
        android:layout_marginBottom="0dp"
        android:hint="Comment anything important about the next measurement(s)"
        android:singleLine="false" />

    <Button
        android:id="@+id/send"
        style="@style/button_text"
        android:layout_alignParentBottom="true"
        android:layout_
        android:layout_
        android:layout_alignParentRight="true"
        android:layout_marginRight="6dp"
        android:layout_toLeftOf="@id/editText"
        android:background="@drawable/red_button"
        android:text="Send" />

</RelativeLayout>

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_
    android:layout_
    tools:context="com.example.mapwithmarker.MapsMarkerActivity" />


</LinearLayout>
</ScrollView>

我想将布局拆分为 3 个不同的选项卡,一个包含 textView 和按钮,一个包含 graphView 和一个地图。我想我必须对 ViewPager 做点什么,但我不理解 android 指南 (https://developer.android.com/training/implementing-navigation/lateral) 上的示例,因为它会在 Fragment 对象的集合上滑动,而不是我想要的不同布局。

我该怎么做?有没有其他方法来管理它?


更新问题:

我遵循 BenjyTec 的建议,所以我在我的活动中添加了代码并制作了以下 3 个 xml 布局:

fragment1.xml

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_
android:layout_>

<TextView
    android:id="@+id/textView"
    android:layout_
    android:layout_
    android:scrollbars="vertical"
    android:textSize="18sp" />

<RelativeLayout
    android:layout_
    android:fitsSystemWindows="true"
    android:layout_ >

    <EditText
        android:id="@+id/editText"
        android:layout_
        android:layout_
        android:layout_alignBottom="@+id/send"
        android:layout_marginRight="80dp"
        android:layout_marginBottom="0dp"
        android:hint="Comment anything important about the next measurement(s)"
        android:singleLine="false" />

    <Button
        android:id="@+id/send"
        style="@style/button_text"
        android:layout_alignParentBottom="true"
        android:layout_
        android:layout_
        android:layout_alignParentRight="true"
        android:layout_marginRight="6dp"
        android:layout_toLeftOf="@id/editText"
        android:background="@drawable/red_button"
        android:text="Send" />

</RelativeLayout>

</LinearLayout>

fragment2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_
android:layout_>

<com.jjoe64.graphview.GraphView
    android:id="@+id/graph"
    android:layout_
    android:layout_ />

</LinearLayout>

fragment3.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_
android:layout_>

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_
    android:layout_
    tools:context="com.example.mapwithmarker.MapsMarkerActivity" />

</LinearLayout>

所以,现在的主要布局(second.xml)是:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:fitsSystemWindows="true"
android:orientation="vertical">

<android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_
    android:layout_ />

</LinearLayout>

但现在当我运行应用程序时,它会崩溃并出现以下错误:

java.lang.RuntimeException:无法启动活动 组件信息com.redbear.chat/com.redbear.chat.Chat: java.lang.NullPointerException:尝试调用虚拟方法'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' 在空对象引用上 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 在 android.app.ActivityThread.-wrap11(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5443) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 引起:java.lang.NullPointerException:尝试调用虚拟方法'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' 在空对象引用上 在 com.redbear.chat.Chat.onCreate(Chat.java:185) 在 android.app.Activity.performCreate(Activity.java:6245) 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130) 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 在 android.app.ActivityThread.-wrap11(ActivityThread.java) 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5443) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

我的活动如下:

public class Chat extends FragmentActivity implements OnMapReadyCallback 

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.second);

    ViewPager viewPager = findViewById(R.id.viewPager);
    viewPager.setOffscreenPageLimit(2);  //number of ViewPager pages that will be kept in storage while swiping
    ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(viewPagerAdapter);

    SupportMapFragment mapFragment = (SupportMapFragment) this.getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    graph = (GraphView) findViewById(R.id.graph);
    tv = (TextView) findViewById(R.id.textView);
    tv.setMovementMethod(ScrollingMovementMethod.getInstance());
    et = (EditText) findViewById(R.id.editText);
    btn = (Button) findViewById(R.id.send);


public class ViewPagerAdapter extends FragmentPagerAdapter 

    public ViewPagerAdapter(FragmentManager manager) 
        super(manager);
    

    @Override
    public Fragment getItem(int position) 
        switch (position) 
            case 0:
                return new FragmentA();
            case 1:
                return new FragmentB();
            case 2:
                return new FragmentC();
        
        return new FragmentA();
    

    @Override
    public int getCount() 
        return 3;  //number of Fragments inside the ViewPager
    



public static class FragmentA extends Fragment 

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        ViewGroup rootView = (ViewGroup) inflater.inflate(
                R.layout.fragment1, container, false);

        return rootView;
    


public static class FragmentB extends Fragment 

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        ViewGroup rootView = (ViewGroup) inflater.inflate(
                R.layout.fragment2, container, false);

        return rootView;
    


public static class FragmentC extends Fragment  

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) 
        ViewGroup rootView = (ViewGroup) inflater.inflate(
                R.layout.fragment3, container, false);

        return rootView;
    


private GoogleMap mMap;

@Override
public void onMapReady(GoogleMap googleMap) 
    mMap = googleMap;

    // Add a marker in Sydney, Australia, and move the camera.
    LatLng patras = new LatLng(38.246639, 21.734573);
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(patras, 14));
    updateLocationUI();
    UiSettings set = mMap.getUiSettings();
    set.setZoomControlsEnabled(true);


private void updateLocationUI() 
    if (mMap == null) 
        return;
    
    try 
        mMap.setMyLocationEnabled(true);
        mMap.getUiSettings().setMyLocationButtonEnabled(true);
     catch (SecurityException e)  
        Log.e("Exception: %s", e.getMessage());
    



【问题讨论】:

【参考方案1】:

您可以按照文档中的示例创建三个具有三种不同布局的 Fragment 并将它们添加到 ViewPager。 假设您有三个片段FragmentAFragmentBFragmentC,具有相应的布局,a_fragment.xml 带有 TextView 和 Button,b_fragment.xml 带有 GraphView,c_fragment.xml 包含地图。

现在在你的 activity_main.xml 布局中:

<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_
    android:layout_>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_
        android:layout_
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.constraintlayout.widget.ConstraintLayout>

在 MainActivity.java 中设置您的 ViewPager,如下所示:

ViewPager viewPager = findViewById(R.id.viewPager);
viewPager.setOffscreenPageLimit(2);  //number of ViewPager pages that will be kept in storage while swiping
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(viewPagerAdapter);

最后像这样创建一个 ViewPagerAdapter 类:

public class ViewPagerAdapter extends FragmentPagerAdapter 

    public ViewPagerAdapter(FragmentManager manager) 
        super(manager);
    

    @Override
    public Fragment getItem(int position) 
        switch (position) 
            case 0:
                return new FragmentA();
            case 1:
                return new FragmentB();
            case 2:
                return new FragmentC();
        
        return new FragmentA();
    

    @Override
    public int getCount() 
        return 3;  //number of Fragments inside the ViewPager
    


现在将设置TextView、Button、GraphView、Map的代码移到对应的Fragments中。例如FragmentBonCreateView 内的代码是这样的:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)  
    View rootView = inflater.inflate(R.layout.fragment2, container, false); 

    GraphView graphView = rootView.findViewById(R.id.graph);

    return rootView; 

以同样的方式,您将 Map 的所有代码移动到相应的 Fragment 中,在您的情况下为 FragmentC

【讨论】:

它帮助了我,非常感谢你,但现在我猜地图有错误......请查看我帖子中的更新。 应用程序可能会崩溃,因为您在MainActivityonCreate 内设置了视图(TextView、Button、GraphView、地图),但MainActivity 的布局不包含这些观点不再!所以一个NullpointerException 被抛出。所以需要在对应的Fragments中设置Views。请参阅我编辑的答案。 我现在已经在对应的fragment中设置了view,但是因为mapFragment.getMapAsync(this)还是抛出了“java.lang.NullPointerException”的错误; FragmentC 中的mapFragment.getMapAsync(this); 替换为mapFragment.getMapAsync(getActivity);。希望这最终会成功...... 好的,通过在 mapFragment 初始化中使用 getChildFragmentManager() 而不是 getSupportFragmentManager() 解决了最后一个问题。非常感谢您给我答案!

以上是关于如何将布局拆分为 3 个不同的滑动视图的主要内容,如果未能解决你的问题,请参考以下文章

如何根据不同的屏幕尺寸测量和布局视图

如何在批处理脚本中将字符串拆分为 3 个不同的字符串?

Android Studio 滑动到不同的视图

如何将 TabbedPage ContentPage 拆分为不同的文件

如何在自动布局中设置视图下方不同数量按钮的宽度

如何在拆分视图iOS中将不同的视图加载到详细视图