Android动态片段加载进度条的可见性不会设置

Dan*_*Dan 4 android android-layout android-fragments

我正在使用Android片段加载我的应用程序中的代码.要创建一个简单的加载器LoadingFragment extends Fragment,然后我的片段类扩展它,例如:MyFragment extends LoadingFragment.

LoadingFragment具有hideLoadershowLoader理论上我的子类片段应该能够在来电onCreateViewonPostExecute来显示和隐藏在负载之间的进度条.

布局明智我有一个main_layout.xml动态片段的framelayout和一个包含进度条的静态relativelayout.

目前我的片段加载并从另一个内部替换元素,但我删除了该代码.

问题

这个问题是setVisibiltyLoadingFragment似乎从子类中调用它时,例如具有零效果MyFragment,这是为什么?

我已经给出了LoadingFragment它自己的View变量viewMaster,我认为应该参考main_layout但仍然可见性变化似乎没有效果?

主要活动

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

LoadingFragment

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

MyFragment

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();
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

main_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>
Run Code Online (Sandbox Code Playgroud)

kri*_*son 9

这个问题是setVisibilityLoadingFragment似乎从子类中调用它时,例如具有零效果MyFragment,这是为什么?

让我们来看看MyFragment onCreateView调用时会发生什么:

你打电话给super onCreateView哪个LoadingFragment.这会膨胀main_layout并返回膨胀的视图.请注意,此视图未在MyFragment(即View mainLayout = super.onCreateView(inflater, container, savedInstanceState);)中 引用

您刚刚对具有loading视图组的视图进行了充气,然后将其丢弃.但是,您确实设法在LoadingFragment超类中保存对该视图的引用.

接下来你膨胀R.layout.fragment_lans并且(在开始加载之后)将该视图作为要在片段中使用的视图返回.

所以在这里要观察的是,LoadingFragment现在有一个对片段的活动视图层次结构中没有的视图的引用.

鉴于此,难怪setVisibility不会做任何事情,因为片段没有显示该视图.

我不会使用继承来做这件事,但如果你必须使用它,这里是如何解决你的问题.

  1. 我们只使用ProgressBar没有视图组包装器.因为它在a中RelativeLayout,让我们把它放在中心位置.然后使它android:visibility="gone"有效地脱离片段布局:

            <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"/>
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 更改,LoadingFragment以便a)它不会干扰其子类'布局的膨胀,b)它使用子类'活动视图层次结构中的进度条:

    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);
               }
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

现在您应该看到您的期望.


编辑

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

你的活动正在膨胀main_layout,有进度条,所以我会给活动一些责任.

现在,您可以为片段编写一些代码,这些代码将遍历视图层次结构并查找进度条.这不是我的偏好.

这是另一种方法:

  • 创建一个界面

    interface ProgressDisplay {
    
        public void showProgress();
    
        public void hideProgress();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 让活动实现它

        public class MainActivity extends AppCompatActivity implements ProgressDisplay {
    
    Run Code Online (Sandbox Code Playgroud)

    ...

        public void showProgress() {
            findViewById(R.id.loading).setVisibility(View.VISIBLE);
        }
    
        public void hideProgress() {
            findViewById(R.id.loading).setVisibility(View.GONE);
        }
    
    Run Code Online (Sandbox Code Playgroud)
  • 然后将方法添加到LoadingFragment调用该活动:

        protected void showProgress() {
            if (getActivity() instanceof ProgressDisplay) {
                ((ProgressDisplay) getActivity()).showProgress();
            }
        }
    
        protected void hideProgress() {
            if (getActivity() instanceof ProgressDisplay) {
                ((ProgressDisplay) getActivity()).hideProgress();
            }
        }
    
    Run Code Online (Sandbox Code Playgroud)

这样,您可以使用进度视图进行任何使布局膨胀的活动,并使其实现,ProgressDisplay以便您可以使用LoadingFragment该类.

您也可以创建一个LoadingActivity类和子类.