java-如何获取(或模拟)DialogFragment中的ViewPager?
作者:互联网
我希望有一个包含几页的dialogFragment,以为我的应用输入一些设置.当我使用AlertDialog.Builder时,我收到一个IllegalStateException,上面写着“片段没有视图”,这使我感到困惑(而且堆栈也毫无用处).
我可以在其中弹出一个使用ViewPager的弹出窗口,完全可以执行我想要的操作,但是它没有我想要的按钮.我真的很喜欢默认AlertDialog的外观,因此,如果可能(出于一致性原因),我最好使用它.如果没有,我可以制作一个看起来完全一样的自定义对话框.
因此,如何使ViewPager在AlertDialog / dialogFragment(或类似文件)中工作?
编辑:只是为了澄清,它不必是AlertDialog,但是我想选择设置标题,(永久)消息和按钮的选项.
EDIT2:因此,在FragmentFirst newInstance()中返回f时,出现“片段没有视图”错误.这应该将片段返回到适配器中的getItem()方法,该方法应该返回与正确位置关联的片段.我希望这可以帮助任何人查明出了什么问题.
EDIT3:在弄乱一些东西之后,我现在得到了这个错误:未找到片段FragmentDefault {47febfa#1 id = 0x7f0c00b7 android:switcher:2131493047的ID 0x7f0c00b7(com.example.tim.timapp:id / pager)的视图: 0},基本上是在告诉我某些内容试图在错误的片段中找到寻呼机视图?不太确定如何解决该问题.注意除了其名称和某些ID外,FragmentDefault与FragmentFirst完全相同.
EDIT4:(2016年3月11日)一个问题:当使用newInstance方法(如我在片段内部所做的操作)时,返回的片段应该有视图吗?当我调用if(f.getView()== null)时,它返回true,这使我想知道f甚至是否应该有一个视图.如果是这样,为什么不呢?我在网上看到的每个newInstance方法的布局都与我的布局完全相同,因此看起来好像我没有丢失任何东西.
另外,由于某种原因,片段(FragmentFirst,FragmentSecond等)中的onCreateView永远不会到达.我在onCreateView之后有一个Log.d,它从未显示在logcat中.有任何想法吗?
码:
调用dialogFragment
TestActivityFragment newFragment = new TestActivityFragment();
newFragment.show(getChildFragmentManager(), "dialog");
TestActivityFragment:
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;
}
}
}
碎片之一
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;
}
}
XML的
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
PS.如果我忘记添加一段代码,请告诉我,以便我可以添加它.
解决方法:
因此,我终于设法得到了我想要的东西.不过,有些东西已经改变了.
除了替换return builder.create();之外,onCreateDialog()方法没有改变.使用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);
}
}
}
}
碎片(在原始帖子中作为碎片之一提到的那些碎片已消失.不再需要它们.
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.
只是为了(证明)它正在工作,这是一张图片.
如果您需要更多信息,请随时询问.我已经为此苦苦挣扎很长时间了,因此很高兴为您提供帮助.
标签:android-fragments,android-viewpager,java,android 来源: https://codeday.me/bug/20191118/2032185.html