我正在使用Android片段加载我的应用程序中的代码。要创建一个简单的加载器,我有LoadingFragment extends Fragment
,然后我的片段类扩展了它,例如:MyFragment extends LoadingFragment
。
LoadingFragment
有hideLoader
和showLoader
理论上我的子类Fragment应该能够在onCreateView
和onPostExecute
中调用以显示和隐藏进度条在负载之间。
布局明智我有一个main_layout.xml
,其中包含动态片段的framelayout和一个包含进度条的静态relativelayout。
目前我的片段加载并从另一个内部替换点击元素,但我删除了该代码。
问题
问题是setVisibilty
中的LoadingFragment
在从子类调用时似乎没有效果,例如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();
}
}
但仍然可见性变化似乎无效?
MainActivity
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);
}
}
LoadingFragment
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();
}
}
}
MyFragment
<?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>
main_layout.xml
ReportDocument report = new ReportDocument();
答案 0 :(得分:9)
问题是
setVisibility
中的LoadingFragment
在从子类调用时似乎没有效果,例如MyFragment
,为什么会这样?
让我们看一下调用MyFragment onCreateView
时会发生什么:
您拨打super
中的onCreateView
LoadingFragment
。这会使main_layout
膨胀并返回膨胀的视图。请注意,此视图未在MyFragment
中引用(即View mainLayout = super.onCreateView(inflater, container, savedInstanceState);
)
您刚刚对包含loading
视图组的视图进行了充气,然后将其丢弃。但是,您确实设法在LoadingFragment
超类中保存对该视图的引用。
接下来你膨胀R.layout.fragment_lans
并且(在开始加载之后)将那个视图作为要在片段中使用的视图返回。
所以要注意的是LoadingFragment
现在引用了一个在片段的活动视图层次结构中没有的视图。
鉴于此,毫无疑问setVisibility
没有做任何事情,因为片段没有显示该视图。
我不会使用继承来执行此操作,但如果您必须使用它,那么这里是如何解决您的问题。
我们只使用没有视图组包装器的ProgressBar
。因为它在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"/>
您将把这个进度条放在每个LoadingFragment
子类的布局中,包括fragment_lans.xml
。您可以使用<include>
标记来简化生活。
更改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);
}
}
}
}
现在你应该看到你的期望了。
修改
如果确实想要使用您开始使用的布局方案,这是我的建议:
您的活动正在膨胀具有进度条的main_layout
,因此我会对该活动承担部分责任。
现在,您可以为片段编写一些代码,这些代码将遍历视图层次结构并查找进度条。那不是我的偏好。
这是另一种方法:
创建界面
interface ProgressDisplay {
public void showProgress();
public void hideProgress();
}
让活动实现它
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
:
protected void showProgress() {
if (getActivity() instanceof ProgressDisplay) {
((ProgressDisplay) getActivity()).showProgress();
}
}
protected void hideProgress() {
if (getActivity() instanceof ProgressDisplay) {
((ProgressDisplay) getActivity()).hideProgress();
}
}
通过这种方式,您可以使用进度视图执行任何夸大布局的活动,并让它实现ProgressDisplay
,以便您可以使用LoadingFragment
类。
你也可以创建一个LoadingActivity
类和子类。
答案 1 :(得分:2)
您通过View上的showLoader调用setVisibility,因为您将其他视图作为片段视图返回,因此不会用于在屏幕上绘制。
这样的事情应该有效(MyFragment):
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="http://fonts.googleapis.com/css?family=Open+Sans:400,300,700" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="style.css" />
<!-- Resource style -->
<script src="js/modernizr.js"></script>
<!-- Modernizr -->
<title>Switch......</title>
</head>
<body>
<main id="barba-wrapper">
<div class="cd-index barba-container">
<div>
<h1>Animated Page Transition</h1>
<a class="cd-btn" href="about.html" data-type="page-transition"><svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="200px" height="1.49468in" version="1.1" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 4386 1167"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style type="text/css">
<![CDATA[
.fil0 {fill:#FFCC29}
]]>
</style>
</defs>
<g id="Layer_x0020_1">
<metadata id="CorelCorpID_0Corel-Layer"/>
<path class="fil0" d="M583 0l3219 0c321,0 584,262 584,583l0 0c0,321 -263,584 -584,584l-3219 0c-321,0 -583,-263 -583,-584l0 0c0,-321 262,-583 583,-583zm1198 262c-39,-44 -111,-74 -198,-74 -156,0 -264,112 -264,259 0,105 63,158 129,196 57,33 81,63 81,105 0,57 -48,92 -95,92 -47,0 -91,-22 -120,-56l-98 124c43,47 125,82 219,82 135,0 264,-86 264,-262 0,-111 -78,-168 -136,-203 -51,-30 -75,-51 -75,-93 0,-65 54,-96 93,-96 39,0 77,17 102,46l98 -120zm729 148l-158 0 -126 367 -2 0 -5 -367 -133 0 -136 367 -2 0 6 -367 -157 0 20 561 157 0 139 -346 1 0 7 346 163 0 226 -561zm230 0l-158 0 -97 561 158 0 97 -561zm35 -170c0,-47 -29,-81 -81,-81 -55,0 -94,49 -94,104 0,42 28,80 78,80 55,0 97,-46 97,-103zm348 170l-95 0 25 -137 -153 0 -23 137 -74 0 -22 126 74 0 -47 270c-3,17 -5,35 -5,48 0,79 47,127 141,127 27,0 61,-8 82,-18l20 -119c-10,3 -26,6 -38,6 -31,0 -46,-16 -46,-47 0,-9 2,-25 4,-37l42 -230 91 0 24 -126zm390 26c-25,-23 -61,-43 -130,-43 -169,0 -270,193 -270,373 0,124 56,222 189,222 53,0 99,-16 129,-41l-41 -124c-17,12 -34,21 -57,21 -46,0 -66,-36 -66,-96 0,-91 42,-212 112,-212 27,0 41,10 53,23l81 -123zm478 93c0,-64 -32,-136 -123,-136 -69,0 -114,43 -144,94l-2 0 59 -332 -157 0 -142 816 157 0 57 -329c11,-65 45,-110 88,-110 34,0 44,25 44,55 0,13 -2,27 -4,40l-61 344 158 0 59 -344c7,-35 11,-71 11,-98l0 0zm-3350 442c220,0 398,-178 398,-398 0,-220 -178,-398 -398,-398 -220,0 -398,178 -398,398 0,220 178,398 398,398zm-80 -387l79 -330 142 34 -80 330 -141 -34zm139 189c14,-58 -22,-115 -79,-129 -57,-14 -115,21 -129,79 -14,57 22,115 79,128 57,14 115,-21 129,-78z"/>
</g>
</svg>
</a>
</div>
</div>
</main>
<div class="cd-cover-layer"></div>
<div class="cd-loading-bar"></div>
<script data-require="jquery@3.0.0" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script src="app.js"></script>
<!-- Resource jQuery -->
</body>
</html>
答案 2 :(得分:0)
如果您正在使用继承,则无法将布局分配给父片段。
您可以利用像这样的butterknife的View Binding继承,并编写更干净的代码。
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.emerson.techdayapp.R;
import com.emerson.techdayapp.view.activity.MainActivity ;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Base fragment created to be extended by every fragment in this application. This class provides
* dependency injection configuration, ButterKnife Android library configuration and some methods
* common to every fragment.
*/
public abstract class BaseFragment extends Fragment {
private Unbinder unbinder;
@BindView(R.id.htab_toolbar)
Toolbar mToolbar;
@BindView(R.id.loading_view)
ProgressBar loadingView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(getFragmentLayout(), container, false);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//bind view
injectViews(view);
//set page title
setUpToolBar(getPageTitle());
//add click listeners
setUpViewEvents();
//make service call
fillData();
}
/**
* @return resource if of fragment layout
*/
protected abstract int getFragmentLayout();
/**
* Set toolbar title
*
* @return
*/
protected abstract String getPageTitle();
/**
* Add click listeners
*/
protected abstract void setUpViewEvents();
/**
* Make Web serve calls here
*/
protected abstract void fillData();
/**
* Inject View
*
* @param view
*/
private void injectViews(final View view) {
unbinder = ButterKnife.bind(this, view);
}
/**
* Set up toolbar
*
* @param pageTitle
*/
private void setUpToolBar(String pageTitle) {
getActivity().setTitle(pageTitle);
if (mToolbar != null) {
((MainActivity ) getActivity()).setSupportActionBar(mToolbar);
((MainActivity ) getActivity()).getSupportActionBar()
.setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationIcon(R.drawable.ic_drawer);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO what to do on back press
}
});
mToolbar.setTitleTextColor(Color.WHITE);
}
}
public void showProgressDialog() {
if (null != loadingView)
loadingView.setVisibility(View.VISIBLE);
}
public void dismissProgressDialog() {
if (null != loadingView)
loadingView.setVisibility(View.GONE);
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}
然后使用像这样的基础片段
public class MyFragment extends BaseFragment {
public MyFragment() {
}
public static MyFragment newInstance() {
MyFragment fragment = new MyFragment();
return fragment;
}
@Override
protected int getFragmentLayout() {
//put your frag layout id here
return R.layout.frag_pulse;
}
@Override
protected String getPageTitle() {
//Add some title to page
return "Some Title";
}
@Override
protected void setUpViewEvents() {
}
@Override
protected void fillData() {
new AsyncTask<String, Void, String>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
//Show Progress
showProgressDialog();
}
@Override
protected String doInBackground(String... strings) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//Hide Progress
dismissProgressDialog();
}
};
}
}
此处需要注意的是,您的片段布局必须包含一个工具栏ID htab_toolbar
和一个ID为loading_view
的进度条,因为它由基类使用