【问题标题】:Tabs not working properly when switching in android studio在android studio中切换时选项卡无法正常工作
【发布时间】:2017-02-02 09:31:48
【问题描述】:

我是原生安卓开发的新手。我正在使用android studio 开发应用程序。我正在使用 tabbed-activity 并使用 3 个选项卡。所有 3 个选项卡都有单独的 classeslayouts,其名称如下图所示。

类和布局名称与图片中显示的相同。

我的标签有以下功能。

  1. 在第一个选项卡上,我实现了 google map v2,它显示了我当前的 gps 位置以及坐标和标记。
  2. 在第二个选项卡上,我实现了一个camera,我在其中放置了一个按钮和一个image view。通过按下按钮,相机将显示,当我拍照时,它会在图像视图中显示我。这张图片也保存到我的SD CARD 中。
  3. 在第三个也是最后一个选项卡中,我添加了一个gird view,它将从SD CARD 获取这些图像并将其显示在网格上。

对于third tab,我关注了tutorial,因此我分别制作了2 个helper 和1 个adapter 课程。 2 个辅助类是 AppConstantUtils,适配器被命名为 GridViewImageAdapter,它扩展了 BaseAdapter

以上所有 3 个(2 个帮助程序和 1 个适配器)类都导入到我的 pictures 类中。

现在,当我第一次运行该应用程序时,我可以看到我当前的位置。但是当我点击camera 选项卡时,它会转到Util 类,当它找不到任何文件时,应用程序就会崩溃。这不应该发生,因为我的 Util 类仅在 pictures 片段中导入,与 camera 片段无关。下面是代码部分

Camera.java

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

    button = (Button)rootView.findViewById(R.id.getpicture);
    imageView = (ImageView)rootView.findViewById(R.id.imageView);

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Check permission for CAMERA
            if (ActivityCompat.checkSelfPermission(getActivity(), CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {

                // Check Permissions Now
                // Callback onRequestPermissionsResult interceptado na Activity MainActivity
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{CAMERA},
                        Camera.REQUEST_CAMERA);

            }
            else {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE );

            }


        }
    });



    return rootView;
}
//For saving image(s)
private void SaveImage(Bitmap finalBitmap) {

    String root = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
    Log.v(getTag(), root);
    File myDir = new File(root + "/saved_images");
    myDir.mkdirs();
    Random generator = new Random();
    int n = 10000;
    n = generator.nextInt(n);
    String fname = "Image-" + n + ".jpg";
    File file = new File(myDir,fname);
    if (file.exists())file.delete();
    try {
        FileOutputStream out = new FileOutputStream(file);
        finalBitmap.compress(Bitmap.CompressFormat.JPEG,90,out);
        out.flush();
        out.close();


    } catch (Exception e) {
        e.printStackTrace();
    }
    //Toast.makeText(getContext(), "Image is saved", Toast.LENGTH_LONG).show();
}

下面是我的图片代码

Pictures.java

import com.example.accurat.faisal.adapter.GridViewImageAdapter;
import com.example.accurat.faisal.helper.Utils;
import com.example.accurat.faisal.helper.AppConstant;
//other imports
 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.pictures, container, false);

    gridView = (GridView)rootView.findViewById(R.id.grid_view);
    utils = new Utils(getContext());

    // Initilizing Grid View
    InitilizeGridLayout();

    // loading all image paths from SD card
    imagePaths = utils.getFilePaths();

    // Gridview adapter

    adapter = new GridViewImageAdapter(getActivity(), imagePaths, columnWidth);
    /*adapter = new GridViewImageAdapter(Pictures.this, imagePaths,
            columnWidth);*/

    // setting grid view adapter
    gridView.setAdapter(adapter);


    return rootView;
}

private void InitilizeGridLayout() {

    Resources r = getResources();
    float padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
            AppConstant.GRID_PADDING, r.getDisplayMetrics());

    columnWidth = (int) ((utils.getScreenWidth() - ((AppConstant.NUM_OF_COLUMNS + 1) * padding)) / AppConstant.NUM_OF_COLUMNS);

    gridView.setNumColumns(AppConstant.NUM_OF_COLUMNS);
    gridView.setColumnWidth(columnWidth);
    gridView.setStretchMode(GridView.NO_STRETCH);
    gridView.setPadding((int) padding, (int) padding, (int) padding,
            (int) padding);
    gridView.setHorizontalSpacing((int) padding);
    gridView.setVerticalSpacing((int) padding);
}

上面的这个类将访问helperadapter 方法。帮助方法见下文

Utils.java

public class Utils {

         // Reading file paths from SDCard
public ArrayList<String> getFilePaths() {
    ArrayList<String> filePaths = new ArrayList<String>();

    File directory = new File(
            android.os.Environment.getExternalStorageDirectory(),AppConstant.PHOTO_ALBUM);

    // check for directory
    if (directory.isDirectory()) {
        // getting list of file paths
        File[] listFiles = directory.listFiles();

        // Check for count
        if (listFiles.length > 0) {

            // loop through all files
            for (int i = 0; i < listFiles.length; i++) {

                // get file path
                String filePath = listFiles[i].getAbsolutePath();

                // check for supported file extension
                if (IsSupportedFile(filePath)) {
                    // Add image path to array list
                    filePaths.add(filePath);
                }
            }
        } else {
            // image directory is empty
            Toast.makeText(
                    _context,
                    AppConstant.PHOTO_ALBUM
                            + " is empty. Please load some images in it !",
                    Toast.LENGTH_LONG).show();
        }

    } else {
        AlertDialog.Builder alert = new AlertDialog.Builder(_context);
        alert.setTitle("Error!");
        alert.setMessage(AppConstant.PHOTO_ALBUM
                + " directory path is not valid! Please set the image directory name AppConstant.java class");
        alert.setPositiveButton("OK", null);
        alert.show();
    }

    return filePaths;
   }
}

本课程中还有其他方法,但我只发布了上述方法,因为当我转到 pictures 选项卡时,首先调用此方法,它适用于图片选项卡,但当我转到 camera 时再次选项卡调用上述方法并且应该调用它,因为我的相机类中没有任何内容可以访问帮助程序类。我不知道为什么会这样,因为所有类都是分开的,所以它不应该像这样工作,我得到null exception

清单见下文

 <uses-permission android:name="com.example.accurat.faisal.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

下面是错误

FATAL EXCEPTION: main
              Process: com.example.accurat.faisal, PID: 25624
              java.lang.NullPointerException: Attempt to get length of null array
                  at com.example.accurat.faisal.helper.Utils.getFilePaths(Utils.java:42)
                  at com.example.accurat.faisal.Pictures.onCreateView(Pictures.java:45)
                  at android.support.v4.app.Fragment.performCreateView(Fragment.java:2184)
                  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1298)
                  at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(FragmentManager.java:2323)
                  at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2136)
                  at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2092)
                  at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1969)
                  at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:620)
                  at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143)
                  at android.support.v4.view.ViewPager.populate(ViewPager.java:1268)
                  at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:668)
                  at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:630)
                  at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:611)
                  at android.support.design.widget.TabLayout$ViewPagerOnTabSelectedListener.onTabSelected(TabLayout.java:2178)
                  at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1155)
                  at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1148)
                  at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1118)
                  at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1413)
                  at android.support.design.widget.TabLayout$TabView.performClick(TabLayout.java:1523)
                  at android.view.View$PerformClick.run(View.java:22596)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:7325)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Utlis.java:42

 // check for directory
    if (directory.isDirectory()) {
        // getting list of file paths
        File[] listFiles = directory.listFiles();

        // Check for count
        if (listFiles.length > 0) {// do the needful

Pictures.java:42// loading all image paths from SD card imagePaths = utils.getFilePaths();

更新 1

根据Mike MRuben2112 的建议,我将READ_EXTERNAL_STORAGE 导入到我的每个助手和适配器类中,并在Utils 类中检查listFiles,如下所示

 File directory = new File(
            android.os.Environment.getExternalStorageDirectory(),AppConstant.PHOTO_ALBUM);

    // check for directory
    if (directory.isDirectory()) {
        // getting list of file paths
        File[] listFiles = directory.listFiles();

        if (listFiles != null) {// Check for list files
            // Check for count
            if (listFiles.length > 0) {

                // loop through all files
                for (int i = 0; i < listFiles.length; i++) {

                    // get file path
                    String filePath = listFiles[i].getAbsolutePath();

                    // check for supported file extension
                    if (IsSupportedFile(filePath)) {
                        // Add image path to array list
                        filePaths.add(filePath);
                    }
                }
            } else {
                // image directory is empty
                Toast.makeText(
                        _context,
                        AppConstant.PHOTO_ALBUM
                                + " is empty. Please load some images in it !",
                        Toast.LENGTH_LONG).show();
            }

        } else {
            AlertDialog.Builder alert = new AlertDialog.Builder(_context);
            alert.setTitle("Error!");
            alert.setMessage(AppConstant.PHOTO_ALBUM
                    + " directory path is not valid! Please set the image directory name AppConstant.java class");
            alert.setPositiveButton("OK", null);
            alert.show();
        }
    }

现在我的应用程序没有崩溃,但它仍然在警告框中显示错误,如下图所示

点击确定后,应用程序仍然运行

我坚持下去,不知道该怎么办。任何帮助将不胜感激。

【问题讨论】:

  • 默认情况下,ViewPager 将加载下一个相邻页面,以便将它们拉到屏幕上。当您导航到第二个选项卡时,它正在准备第三页。查看您的 Utils 类,如果 AppConstant.PHOTO_ALBUM 确实是一个常量,它看起来无论如何都会崩溃。它崩溃了,因为 directory.listFiles() 返回 null。如果您在 Marshmallow 或更高版本上运行,您确定您已正确处理权限吗? READ_EXTERNAL_STORAGE 是一个危险的权限。你需要请求它,就像你是CAMERA
  • @MikeM。是的,我添加了权限检查。在棉花糖上,应用程序崩溃,但在 API utils 类并显示一个警告框。我想知道如何处理标签的切换
  • 好的,我没有看到READ_EXTERNAL_STORAGE 权限的请求,所以我想我会指出来。无论如何,这就是您需要解决的问题,而不是标签切换。我很确定无论如何都会崩溃。我真的不认为这仅仅是因为您在第二页时加载了第三页。这是因为您无法读取PHOTO_ALBUM 目录。
  • 我的Camera 中有READ_EXTERNAL_STORAGE。此外,如果我创建一个文件夹并将其粘贴到我的设备上,那么该应用程序可以完美运行。
  • 好的,我想我在关注你了。 AppConstant.PHOTO_ALBUM"/saved_images" 文件夹吗?如果是这样,那是因为第三页试图在第二页创建它之前访问该文件夹。你必须决定你想如何处理它。您可以预先请求所有权限,并尽快创建该文件夹。或者你可以推迟加载GridView;即,不要尝试将其加载到onCreateView()

标签: java android android-fragments tabs camera


【解决方案1】:

这不应该发生,因为我的 Util 类只导入到图片片段中,与相机片段无关。

使用选项卡时要意识到的重要一点是,直接在打开的选项卡旁边的选项卡也会被加载。这是因为选项卡已经加载,因此过渡更平滑,这就是滑动的方式转到下一个选项卡。

【讨论】:

  • 那有什么解决办法呢?
  • 你可能需要在获取到 directory.listFiles() 后检查 listFiles 是否为空;
  • 好的,我会检查一下
  • 根据您的建议,我对我的代码做了一些事情。请参阅update 1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多