Android动态 fragment 加载进度条可见性不会设置

标签 android android-layout android-fragments

我正在使用 Android fragment 在我的应用程序中加载代码。为了创建一个简单的加载器,我使用了 LoadingFragment extends Fragment,然后我的 fragment 类对其进行了扩展,例如:MyFragment extends LoadingFragment

LoadingFragmenthideLoadershowLoader 理论上我的子类 Fragment 应该能够调用 onCreateViewonPostExecute 在加载之间显示和隐藏进度条。

在布局方面,我有一个 main_layout.xml,它有一个用于动态 fragment 的框架布局和一个包含进度条的静态相对布局。

目前我的 fragment 加载并从元素的点击中替换,但我已经删除了该代码。

问题

问题是 LoadingFragment 中的 setVisibilty 从子类调用时似乎效果为零,例如 MyFragment,这是为什么?

我给了 LoadingFragment 它是 viewMaster 自己的 View 变量,我认为它应该引用 main_layout 但仍然是可见性更改似乎没有效果?

主 Activity

public class MainActivity extends AppCompatActivity {

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

        MyFragment myFragment = MyFragment.newInstance();

        getSupportFragmentManager().beginTransaction()
            .replace(R.id.fragment_holder, myFragment).commit();
    }
}

加载 fragment

public class LoadingFragment extends Fragment {

    View viewMaster;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        viewMaster = inflater.inflate(R.layout.main_layout, container, false);

        return viewMaster;
    }

    public void showLoader() {

        viewMaster.findViewById(R.id.fragment_holder).setVisibility(View.INVISIBLE);
        viewMaster.findViewById(R.id.loading).setVisibility(View.VISIBLE);
    }

    public void hideLoader() {

        viewMaster.findViewById(R.id.fragment_holder).setVisibility(View.VISIBLE);
        viewMaster.findViewById(R.id.loading).setVisibility(View.INVISIBLE);
    }
}

我的 fragment

public class MyFragment extends LoadingFragment {

    View view;

    public MyFragment() {}

    public static MyFragment newInstance() {
        MyFragment fragment = new MyFragment();
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        super.onCreateView(inflater, container, savedInstanceState);
        super.showLoader();

        view = inflater.inflate(R.layout.fragment_lans, container, false);

        MyFragment.ApiCallJob apicalljob = new MyFragment.ApiCallJob();
        apicalljob.execute("a string");

        return view;
    }

    public class ApiCallJob extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String[] params) {
            // do things
        }

        @Override
        protected void onPostExecute(String data) {
            // do things
            // tried both to be sure but they should do the same?  
            hideLoader();
            MyFragment.super.hideLoader();
        }
    }

}

ma​​in_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="app.stats.MainActivity"
    android:orientation="horizontal">

    <FrameLayout
        android:id="@+id/fragment_holder"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </FrameLayout>

    <RelativeLayout
        android:id="@+id/loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/progress_bar"/>
    </RelativeLayout>

</RelativeLayout>

最佳答案

The issue is the setVisibility in LoadingFragment seems to have zero effect when calling it from the subclasses, for example MyFragment, why is this?

让我们看看当 MyFragment onCreateView 时会发生什么被称为:

你调用super onCreateView这是在 LoadingFragment .这会膨胀 main_layout并返回膨胀 View 。请注意,此 View 未在 MyFragment 中引用(即 View mainLayout = super.onCreateView(inflater, container, savedInstanceState);)

您刚刚膨胀了具有 loading 的 View 查看组,然后把它扔掉。但是,您确实设法在 LoadingFragment 中保存对该 View 的引用。父类(super class)。

接下来你膨胀R.layout.fragment_lans并且(在开始加载之后)您返回那个 View 作为要在 fragment 中使用的 View 。

所以这里要注意的是 LoadingFragment现在有一个 View 的引用,该 View 不在 fragment 的 Activity View 层次结构中。

鉴于此,难怪 setVisibility不执行任何操作,因为该 fragment 未显示该 View 。

我不会使用继承来做到这一点,但如果你必须使用它,这里是解决你的问题的方法。

  1. 我们只使用 ProgressBar没有 View 组包装器。因为它在 RelativeLayout 中, 让我们把它居中。然后制作android:visibility="gone"所以它实际上不在 fragment 布局中:

            <ProgressBar
                android:id="@+id/progress_bar"
                style="?android:attr/progressBarStyleLarge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:visibility="gone"/>
    

    您将把这个进度条放在每个 LoadingFragment 的布局中子类,包括 fragment_lans.xml .您可以使用 <include>标签让这里的生活更轻松。

  2. 更改 LoadingFragment这样 a) 它不会干扰其子类布局的膨胀,并且 b) 它在子类的 Activity View 层次结构中使用进度条:

    public class LoadingFragment extends Fragment {
    
        public void showLoader() {
    
            if (getView() != null) {
               View progressBar = getView().findViewById(R.id.progress_bar);
               if (progressBar != null) {
                   progressBar.setVisibility(View.VISIBLE);
               }
            }
        }
    
        public void hideLoader() {
    
            if (getView() != null) {
               View progressBar = getView().findViewById(R.id.progress_bar);
               if (progressBar != null) {
                   progressBar.setVisibility(View.GONE);
               }
            }
        }
    }
    

现在您应该看到您期望的结果了。


编辑

如果您真的想要使用您开始使用的布局方案,这是我的建议:

您的 Activity 正在膨胀main_layout有进度条,所以我会给 Activity 一些责任。

现在,您可以只为 fragment 编写一些代码,这些代码将遍历 View 层次结构并查找进度条。那不是我的偏好。

这是另一种方法:

  • 创建界面

    interface ProgressDisplay {
    
        public void showProgress();
    
        public void hideProgress();
    }
    
  • 让 Activity 实现它

        public class MainActivity extends AppCompatActivity implements ProgressDisplay {
    

    ...

        public void showProgress() {
            findViewById(R.id.loading).setVisibility(View.VISIBLE);
        }
    
        public void hideProgress() {
            findViewById(R.id.loading).setVisibility(View.GONE);
        }
    
  • 然后将方法添加到LoadingFragment调用 Activity :

        protected void showProgress() {
            if (getActivity() instanceof ProgressDisplay) {
                ((ProgressDisplay) getActivity()).showProgress();
            }
        }
    
        protected void hideProgress() {
            if (getActivity() instanceof ProgressDisplay) {
                ((ProgressDisplay) getActivity()).hideProgress();
            }
        }
    

通过这种方式,您可以采取任何使用进度 View 扩充布局的 Activity ,并让它实现 ProgressDisplay所以你可以使用 LoadingFragment用它上课。

你也可以做一个LoadingActivity也对其进行分类和子类化。

关于Android动态 fragment 加载进度条可见性不会设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41144047/

相关文章:

java - 在android中使用java在点击事件上写在哪里

android - 使用 FragmentStatePagerAdapter 后 fragment 中的重复菜单和数据

android - 当 Activity 在其进程被杀死后重新创建时, fragment 后台是否也恢复了?

java - 如何使用点幻灯片注册 Activity

java - 使用 ArrayList 的 ArrayAdapter

android - 如何修改 android master/detail Activity 中的虚拟内容?

android - 我如何调整空间和文件的整体外观,使其看起来更像图片?

java - 约束布局有空间底部和顶部

java - 为什么当我开始一项新 Activity 时我的背景消失了?

覆盖viewpager内容的Android导航栏