问题描述
在我的应用中,我实现了自定义对话框(该对话框相当复杂布局),方法是扩展DialogFragment。我希望在单击布局中的按钮时弹出此对话框。 (我已经成功实现了)。但是问题在于对话框以一种不稳定的方式显示。
In my app I have implemented this custom dialog (which has a fairly complex layout) by extending DialogFragment. I expect this dialog to pop up when I click a button in my layout. (Which I have successfully achieved). But the problem is that the dialog shows up in a janky manner.
我的自定义对话框类:
public class CustomizeDialog extends DialogFragment implements AdapterView.OnItemSelectedListener {
// field declarations go here
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.customize_dialog, null);
builder.setView(view)
.setTitle("Customize")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Let's go!", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction("fromDialog");
intent.putExtra("ratio",getRatio(paperSizeSpinner.getSelectedItem().toString()));
if(isOrientationSpinnerVisible){
intent.putExtra("isCustom",false);
intent.putExtra("orientation",orientationSpinner.getSelectedItem().toString());
} else {
intent.putExtra("isCustom",true);
}
intentProvider.getIntent(intent);
}
});
widthEditText = view.findViewById(R.id.width_et);
heightEditText = view.findViewById(R.id.height_et);
widthEditText.setEnabled(false);
heightEditText.setEnabled(false);
paperSizeSpinner = view.findViewById(R.id.paper_size_spinner);
orientationSpinner = view.findViewById(R.id.orientation_spinner);
// ArrayList for populating paperSize spinner via paperSizeAdapter
ArrayList<String> paperSizes = new ArrayList<>();
paperSizes.add("A0");
paperSizes.add("A1");
paperSizes.add("A2");
paperSizes.add("A3");
paperSizes.add("A4");
paperSizes.add("A5");
paperSizes.add("Custom");
// ArrayList for populating orientation spinner via orientationAdapter
ArrayList<String> orientation = new ArrayList<>();
orientation.add("Portrait");
orientation.add("Landscape");
// arrayAdapters containing arraylists to populate spinners
ArrayAdapter paperSizeAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, paperSizes);
ArrayAdapter orientationAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, orientation);
paperSizeSpinner.setAdapter(paperSizeAdapter);
orientationSpinner.setAdapter(orientationAdapter);
paperSizeSpinner.setSelection(4);
paperSizeSpinner.setOnItemSelectedListener(this);
orientationSpinner.setOnItemSelectedListener(this);
return builder.create();
}
// These are some important complex ui functionalities
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (parent.getId() == R.id.paper_size_spinner) {
if (position == 6) {
widthEditText.setEnabled(true);
heightEditText.setEnabled(true);
orientationSpinner.setEnabled(false);
isOrientationSpinnerVisible = false;
} else {
widthEditText.setEnabled(false);
heightEditText.setEnabled(false);
orientationSpinner.setEnabled(true);
isOrientationSpinnerVisible = true;
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
// interface used to communicate with the parent activity
public interface IntentProvider {
// this method is used to provide the intent to the parent activity
void getIntent(Intent intent);
}
// instantiating the interface object and throwing error if parent activity does not implement this interface
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
intentProvider = (IntentProvider) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement IntentProvider");
}
}
}
MainActivity类:
MainActivity class:
public class MainActivity extends AppCompatActivity implements CustomizeDialog.IntentProvider {
// field declarations go here
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.image);
// instantiating the dialog
final CustomizeDialog dialog = new CustomizeDialog();
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// showing the dialog on click
dialog.show(getSupportFragmentManager(),"");
}
});
}
// via this method I receive the intent from the dialog
// I know intent might not be the best option for this function but let's let it be here for now
@Override
public void getIntent(Intent intent) {
ratio = intent.getFloatExtra("ratio",3);
isCustom = intent.getBooleanExtra("isCustom",false);
orientation = intent.getStringExtra("orientation");
launchChooser();
}
}
在对话框中让我知道是否需要对话框的布局代码。
Let me know in the comments if you want the layout code for the dialog.
我尝试过的操作
- 实施线程,以便在对话框中准备就绪一个后台线程,并显示在onButtonClick上。但这通常是不允许的,因为除UI线程外,其他任何线程都不应触摸与UI相关的事件。
- 使用onCreateView代替onCreateDialog直接对布局进行膨胀。
- 使对话框成为全局变量,在onCreate中将其初始化,然后显示对话框onButtonClick。
- 切换到 CONSTRAINT LAYOUT >
- 通过将清单的主题设置为清单文件中的活动,将活动用作对话框。
- 将我的应用发布到硬件比我更好的设备中。
什么都没做
- Implementing threading so that my dialog is ready in a background thread and show it onButtonClick. But this is not allowed in general as any other thread except UI thread aren't supposed to touch UI related events.
- Using onCreateView instead of onCreateDialog to inflate the layout directly.
- Making the dialog a global variable, initialized it in onCreate and then show the dialog onButtonClick.
- Switched to CONSTRAINT LAYOUT
- Using an activity as a dialog by setting the dialog theme to the activity in the manifest file.
- Launched my app in a device with better hardware than mine.BUT NOTHING WORKED
我要什么:
为什么我的对话框比较混乱?
Why is my dialog janky? and what I need to do to make the dialog pop up faster?
如果有人想要是我在github上的应用程序仓库的链接。
In case anybody wants here's the link to my app repo on github.
推荐答案
和框架的速度很慢,因为它们需要一些时间来进行计算和碎片处理。因此,解决此问题的方法是立即使用Dialog框架。
AlertDialog and DialogFragment frameworks are slow because they need to some time to do calculations and fragment stuffs. So a solution to this problem is, using the Dialog framework straight away.
- 使用框架的
Dialog对话框= new Dialog(上下文);
- 定义布局,然后使用
dialog.setContentView(R.layout.name_of_layout)
。 - 使用
dialog.findViewById(R.id.name_of_view)
引用对话框布局文件中的视图
- Use the Dialog framework's
Dialog dialog = new Dialog(context);
- Define the layout and then use
dialog.setContentView(R.layout.name_of_layout)
. - Use
dialog.findViewById(R.id.name_of_view)
to reference views from the dialog's layout file
,然后实施逻辑就像活动班级中的任何人一样。阅读正式的,找出适合您的用例的最佳实现。
And then implement the logic just like anyone would do in an activity class. Find out the best implementation for your use case by reading the official documentation.
使用对话框框架为我解决了这个问题。
Using the dialog framework solved the problem for me.
这篇关于对话框弹出非常慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!