- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想要一个包含几页的 dialogFragment
来为我的应用输入一些设置。当我使用 AlertDialog.Builder
时,我得到一个 IllegalStateException
说“Fragment 没有 View ”,这让我很困惑(堆栈也很无用)。
我可以获得一个与其中的 ViewPager
一起工作的弹出窗口,完全按照我想要的方式执行,但它没有我想要的按钮。我真的很喜欢默认 AlertDialog
的外观,所以我最好尽可能使用它(出于一致性原因)。如果不是,我可以制作一个看起来完全一样的自定义对话框。
那么,如何让 ViewPager
在 AlertDialog/dialogFragment
(或类似的)中工作?
编辑: 澄清一下,它不一定是AlertDialog
,但我想要设置标题的选项(永久)消息和按钮。
EDIT2: 所以在 FragmentFirst newInstance()
。这应该向 adapter
中的 getItem()
方法返回一个 fragment ,它应该返回与正确位置关联的 fragment 。我希望这可以帮助任何人查明问题所在。
EDIT3: 在弄乱了一些东西后,我现在得到了这个错误:No view found for id 0x7f0c00b7 (com.example.tim.timapp:id/pager)对于 fragment FragmentDefault{47febfa #1 id=0x7f0c00b7 android:switcher:2131493047:0}
,基本上是在告诉我有什么东西试图在错误的 fragment 中找到寻呼机 View ?不太清楚如何解决这个问题。注意。 FragmentDefault
与 FragmentFirst
完全相同,除了它的名称和一些 id。
EDIT4:(2016 年 3 月 11 日)一个问题:当使用 newInstance
方法时(就像我在 fragment 中所做的那样),返回的 fragment 是否应该具有一个看法?当我调用 if (f.getView() == null)
时,它返回 true,这让我想知道 f
是否应该有一个 View 。如果是这样,为什么不呢?我在网上看到的每个 newInstance
方法都与我的布局完全相同,所以看起来我没有遗漏什么。
此外,由于某些原因, fragment (FragmentFirst、FragmentSecond 等)中的 onCreateView
从未达到。我在 onCreateView
之后有一个 Log.d
,它从不显示在 logcat 中。有什么想法吗?
代码:
调用dialogFragment
TestActivityFragment newFragment = new TestActivityFragment();
newFragment.show(getChildFragmentManager(), "dialog");
测试 Activity fragment :
package com.example.fragments.MainFragments.Test;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.tim.timapp.R;
public class TestActivityFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.test_dialog, null);
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(view)
.setPositiveButton("POS", null)
.setNegativeButton("NEG", null)
.setTitle("TEST_TITLE")
.setMessage("TEST_MESSAGE");
ViewPager mPager = (ViewPager) view.findViewById(R.id.pager);
FragmentStatePagerAdapter mPagerAdapter = new TestAdapter(getChildFragmentManager());
mPager.setAdapter(mPagerAdapter);
return builder.create();
}
private class TestAdapter extends FragmentStatePagerAdapter {
public TestAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch(position) {
case 0: return FragmentFirst.newInstance("FragmentFirst, Instance 1");
case 1: return FragmentSecond.newInstance("SecondFragment, Instance 1");
case 2: return FragmentThird.newInstance("ThirdFragment, Instance 1");
case 3: return FragmentThird.newInstance("ThirdFragment, Instance 2");
default: return FragmentDefault.newInstance("DefaultFragment");
}
}
@Override
public int getCount() {
return 5;
}
}
}
其中一个 fragment
package com.example.fragments.MainFragments.Test;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.example.tim.timapp.R;
public class FragmentFirst extends Fragment{
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.frag_first, container, false);
TextView tv = (TextView) v.findViewById(R.id.tvFragFirst);
tv.setText(getArguments().getString("msg"));
return v;
}
public static FragmentFirst newInstance(String text) {
FragmentFirst f = new FragmentFirst();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
test_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
(我也有 viewPager 作为父布局,里面没有任何东西,没有改变任何东西)
frag_first.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tvFragFirst"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:text="TextView"
android:textAppearance="?android:textAppearanceMedium"/>
</RelativeLayout>
03-09 15:30:55.910 23343-23343/? I/art: Not late-enabling -Xcheck:jni (already on)
03-09 15:30:55.940 23343-23349/? E/art: Failed sending reply to debugger: Broken pipe
03-09 15:30:55.940 23343-23349/? I/art: Debugger is no longer active
03-09 15:30:55.950 23343-23343/? W/System: ClassLoader referenced unknown path: /data/app/com.example.tim.timapp-2/lib/x86_64
03-09 15:30:56.060 23343-23356/? D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
03-09 15:30:56.150 23343-23356/? I/OpenGLRenderer: Initialized EGL, version 1.4
03-09 15:30:56.210 23343-23356/? W/EGL_emulation: eglSurfaceAttrib not implemented
03-09 15:30:56.210 23343-23356/? W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0x7f5f5597db40, error=EGL_SUCCESS
03-09 15:30:58.870 23343-23343/com.example.tim.timapp D/GSF - getChildCount: 0
03-09 15:30:58.910 23343-23343/com.example.tim.timapp D/AndroidRuntime: Shutting down VM
03-09 15:30:58.910 23343-23343/com.example.tim.timapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.tim.timapp, PID: 23343
java.lang.IllegalStateException: Fragment does not have a view
at android.app.Fragment$1.onFindViewById(Fragment.java:2181)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:963)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
at android.app.BackStackRecord.run(BackStackRecord.java:793)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1535)
at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:562)
at android.support.v13.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:168)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1177)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1025)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1545)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1112)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:632)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1465)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:748)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:630)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:18788)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2643)
at android.view.View.measure(View.java:18788)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2100)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1191)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1452)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1107)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6013)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858)
at android.view.Choreographer.doCallbacks(Choreographer.java:670)
at android.view.Choreographer.doFrame(Choreographer.java:606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:844)
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:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
03-09 15:35:59.030 23343-23343/? I/Process: Sending signal. PID: 23343 SIG: 9
附言。如果我忘记添加一段代码,请告诉我,以便我添加。
最佳答案
所以,我终于设法得到了我想要的东西。不过,有些东西已经发生了变化。
onCreateDialog()
方法没有改变,只是将 return builder.create();
替换为 return builder.show();
,以及一些外观上的变化。
正确(咳咳)命名的 TestAdapter
现在是 PagerAdapter
而不是 FragmentStatePagerAdapter
。它可能不漂亮,但它确实有效。
private class TestAdapter extends PagerAdapter {
private int mCurrentPosition = -1;
@Override
public int getCount() {
return pageAmount;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
LayoutInflater inflater = getActivity().getLayoutInflater();
int layoutThingy;
switch(position) {
case 0:
layoutThingy = R.layout.fragment_generalsettingsinputdialog1;
break;
case 1:
layoutThingy = R.layout.fragment_generalsettingsinputdialog2;
break;
case 2:
layoutThingy = R.layout.fragment_generalsettingsinputdialog3;
break;
default:
layoutThingy = R.layout.fragment_viewpagererror;
}
View view = inflater.inflate(layoutThingy, null);
container.addView(view);
view.requestFocus();
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == ((View) object);
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
super.setPrimaryItem(container, position, object);
if (position != mCurrentPosition) {
View view = (View) object;
CustomPager pager = (CustomPager) container;
if (view != null) {
mCurrentPosition = position;
pager.measureCurrentView(view);
}
}
}
}
fragment (那些在原始帖子中提到的 One of the fragments
已经消失了。不再需要它们了。
test_dialog.xml
文件也发生了变化。它现在包含一个自定义 viewpager(和一些页面指示器,但这不是困扰我的部分)。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true">
<com.example.tim.timapp.CustomStuff.CustomPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"/>
<com.viewpagerindicator.CirclePageIndicator
android:id="@+id/circlePageIndicator"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:fillColor="@color/colorPrimary"
app:strokeColor="@color/lightGrey"/>
</LinearLayout>
继续,CustomPager
如下所示:
package com.example.tim.timapp.CustomStuff;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
public class CustomPager extends ViewPager {
private View mCurrentView;
public CustomPager(Context context) {
super(context);
}
public CustomPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mCurrentView == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
int height = 0;
mCurrentView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = mCurrentView.getMeasuredHeight();
if (h > height) height = h;
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void measureCurrentView(View currentView) {
mCurrentView = currentView;
requestLayout();
}
public int measureFragment(View view) {
if (view == null)
return 0;
view.measure(0, 0);
return view.getMeasuredHeight();
}
}
它可能看起来令人生畏,但它并没有比将 viewpager 的大小调整到其当前显示页面的大小更多。它在各种动画中看起来并不漂亮,而且速度很慢,但它每次都能完成这项工作。
最后是 frag_first.xml
XML。这些可以是您想要的任何类型的布局 XML,只要它适合 AlertDialog。
只是为了(证明)显示它正在工作,这是一张图片。
如果您需要更多信息,请随时询问。我已经为此苦苦挣扎了很长时间,所以我很乐意提供帮助。
关于java - 如何在 DialogFragment 中获取(或模拟)ViewPager?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35894949/
我是一名优秀的程序员,十分优秀!