我正在使用 Android fragment 在我的应用程序中加载代码。为了创建一个简单的加载器,我使用了 LoadingFragment extends Fragment
,然后我的 fragment 类对其进行了扩展,例如:MyFragment extends LoadingFragment
。
LoadingFragment
有 hideLoader
和 showLoader
理论上我的子类 Fragment 应该能够调用 onCreateView
和onPostExecute
在加载之间显示和隐藏进度条。
在布局方面,我有一个 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();
}
}
}
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>
最佳答案
The issue is the
setVisibility
inLoadingFragment
seems to have zero effect when calling it from the subclasses, for exampleMyFragment
, 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 。
我不会使用继承来做到这一点,但如果你必须使用它,这里是解决你的问题的方法。
我们只使用
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>
标签让这里的生活更轻松。更改
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/