Java 如何在DialogFragment中获取(或模拟)ViewPager?
我想要一个带有几页的Java 如何在DialogFragment中获取(或模拟)ViewPager?,java,android,android-fragments,android-viewpager,Java,Android,Android Fragments,Android Viewpager,我想要一个带有几页的对话框片段,为我的应用程序输入一些设置。当我使用AlertDialog.Builder时,我得到一个IllegalStateException说“Fragment没有视图”,这让我很困惑(堆栈也很无用) 我可以在其中使用ViewPager弹出窗口,做我想让它做的事情,但它没有我想要的按钮。我非常喜欢默认的AlertDialog的外观,因此如果可能的话,我最好使用它(出于一致性的原因)。如果没有,我可以制作一个看起来完全一样的自定义对话框 那么,如何让ViewPager在Ale
对话框片段
,为我的应用程序输入一些设置。当我使用AlertDialog.Builder
时,我得到一个IllegalStateException
说“Fragment没有视图”,这让我很困惑(堆栈也很无用)
我可以在其中使用ViewPager
弹出窗口,做我想让它做的事情,但它没有我想要的按钮。我非常喜欢默认的AlertDialog
的外观,因此如果可能的话,我最好使用它(出于一致性的原因)。如果没有,我可以制作一个看起来完全一样的自定义对话框
那么,如何让ViewPager
在AlertDialog/dialogFragment
(或类似)中工作
编辑:只是为了澄清一下,它不一定是一个警报对话框
,但我想选择设置标题、(永久性)消息和按钮的选项
EDIT2:因此在FragmentFirst newInstance()
中返回f
时出现“片段没有视图”错误。这将向适配器中的getItem()
方法返回一个片段,该方法将返回与正确位置关联的片段。我希望这有助于任何人找出问题所在
EDIT3:在搞乱了一些东西之后,我现在得到了这个错误:找不到id为0x7f0c00b7(com.example.tim.timapp:id/pager)的片段片段默认{47febfa#1 id=0x7f0c00b7 android:switcher:2131493047:0}
,基本上告诉我有什么东西试图在错误的片段中找到寻呼机视图?我不太清楚如何解决这个问题。注意FragmentDefault
与FragmentFirst
完全相同,只是它的名称和一些id不同
EDIT4:(2016年3月11日)一个问题:当使用newInstance
方法(就像我在片段中所做的那样)时,返回的片段是否应该有视图?当我调用if(f.getView()==null)
时,它返回true,这让我怀疑f
是否应该有一个视图。如果是,为什么不呢?我在网上看到的每个newInstance
方法的布局都与我的完全相同,因此看起来我没有遗漏任何东西。
此外,由于某些原因,片段中的onCreateView
(FragmentFirst、FragmentSecond等)从未到达。我在onCreateView
后面有一个Log.d
,它从未显示在logcat中。有什么想法吗
代码:
调用对话框片段
TestActivityFragment newFragment = new TestActivityFragment();
newFragment.show(getChildFragmentManager(), "dialog");
测试活动片段:
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的
测试对话框.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>
<?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>
注:如果我忘记添加一段代码,请告诉我,这样我就可以添加它。我做了类似的操作,但在视图页面中添加了自定义视图
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<package.CustomViewOne
android:id="@+id/custom_view_one"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<package.CustomViewTwo
android:id="@+id/custom_view_two"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<package.CustomViewThree
android:id="@+id/custom_view_three"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.view.ViewPager>
所以,我终于得到了我想要的东西。但有些东西已经改变了
onCreateDialog()
方法没有改变,除了替换returnbuilder.create()使用返回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\u dialog.xml
文件也已更改。它现在包含一个自定义的viewpager(和一些页面指示器,但这不是困扰我的部分)
它可能看起来令人望而生畏,但除了将viewpager调整到其当前显示页面的大小之外,它没有做更多的事情。它不适合所有类型的动画,而且速度非常慢,但它每次都能完成这项工作
最后是frag_first.xml
xml。这些可以是您想要的任何类型的布局xml,只要它适合AlertDialog
为了(证明)它起作用,这里有一张图片。
如果你需要更多的信息,尽管问吧。我已经为此挣扎了很长时间,所以我很乐意帮助你
(单击以获取更大的版本)我对如何使用它感到有点困惑。我需要创建新视图吗?包在xml中如何工作?您必须用视图类所在的packagename替换包。是的,您需要创建自定义视图并在自定义视图中扩大布局。因此在您的示例中,包将是我添加了一个自定义视图sampl因此,当您创建一个java类CustomViewOne.java时,在类的第一行您将看到包名。因此,取包名并在其旁边添加类名。如果我可以问(为了更好地理解发生了什么),为什么需要三个构造函数(我相信这就是它的名称)对于CustomViewOne?最后一个似乎与前两个做了相同的事情,并添加了一些内容。stacktrace不是无用的,它告诉您缺少一个视图。这是因为您没有在DialogFragment中实现onCreateView()。在这里,我已经对添加onCreateView()做了一些(随机)测试方法添加到dialogFragment。由于onCreateDialog()方法中的视图膨胀,我认为它是可消耗的。晚饭后我将更深入地查看您的链接。刚刚使用onCreateView()运行了一个测试。我应该如何准确地使用它?无论顺序如何,onCreateDialog()都可以在onCreateView之前被调用,如果在onCreateView中设置视图,则会导致该视图的NPE,而在其他视图中,我不知道需要onCreateView()做什么。是的,我想我有点仓促。我自己对其进行了一点测试,在使用onCreateDialog时无法使其与viewPager一起工作,如果
class SlidePagerAdapter extends PagerAdapter {
private ViewPager viewPager;
public SlidePagerAdapter(ViewPager viewPager) {
this.viewPager = viewPager;
}
public View instantiateItem(ViewGroup collection, int position) {
return viewPager.getChildAt(position);
}
@Override
public int getCount() {
return viewPager.getChildCount();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == (object);
}
@Override
public int getItemPosition(Object object) {
for (int i = 0; i < getCount(); i++) {
if (object == viewPager.getChildAt(i)) {
return i;
}
}
return POSITION_NONE;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
viewPager.removeView((View) object);
}
}
public class CustomViewOne extends LinearLayout {
public CustomViewOne(Context context) {
super(context);
initLayout();
}
public CustomViewOne(Context context, AttributeSet attrs) {
super(context, attrs);
initLayout();
}
public CustomViewOne(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initLayout();
}
public void initLayout() {
LayoutInflater.from(getContext()).inflate(R.layout.custom_view_one_layout, this);
}
}
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);
}
}
}
}
<?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>
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();
}
}