Android的AlertDialog在片段中

huangapple go评论64阅读模式
英文:

Android's AlertDialog in fragment

问题

我有一个使用选项卡活动(Tabbed Activity)的应用程序,有3个选项卡,每个选项卡都有一个单独的片段(fragment)和布局(layout)。选项卡3具有一些用户配置设置,例如用户名。用户名显示在一个卡片视图(cardview)内,因此我将该卡片视图设置为可点击,点击时会打开一个带有编辑文本的警告对话框(AlertDialog),用于输入用户名。为了构建此对话框,我找到了2种方法。

第一种方法:(此方法在点击卡片视图时运行(On clicklistener)),它非常有效,我没有任何问题,但感觉不像最佳实践。

AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());

alert.setTitle("Enter your Username");

LayoutInflater inflater = getActivity().getLayoutInflater();
View view1 = inflater.inflate(R.layout.editname_layout, null);
alert.setView(view1);
final EditText input = view1.findViewById(R.id.editname);
alert.setPositiveButton("Save", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        textView.setText(input.getText().toString());
    }
});

alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        // Canceled.
    }
});

alert.show();

**第二种方法:**我构建了一个单独的DialogFragment,并使用接口将数据发送回片段。这种方法似乎是最佳实践,但我遇到了许多问题,例如...当数据发送回片段时,我无法在接收到数据时使用方法"textView.setText",因为我在onCreateView方法之外接收它,因此textView始终返回null。

public class Dialog extends AppCompatDialogFragment {
    
    private Context context;
    public DialogListener listener;

    public Dialog(Context context) {
        this.context = context;
    }

    @NonNull
    @Override
    public android.app.Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.name_layout, null);
        final EditText name = (EditText) view.findViewById(R.id.editname);
        builder.setView(view)
                .setTitle("Username")
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                    }
                })
                .setPositiveButton("Save", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        String text = name.getText().toString();
                        listener.data(text);
                        Toast.makeText(getActivity(), "Saved", Toast.LENGTH_SHORT).show();
                    }
                });

         return builder.create();
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);

        try {
            Fragment fragment = new Tab3();
            listener = (DialogListener) fragment;
        }
        catch (ClassCastException e) {
            throw new ClassCastException(context.toString() + " must implement DialogListener");
        }
    }

    public interface DialogListener {
        void data(String name);
    }
}

因此,我正在考虑使用第一种方法,因为它更简单,更容易从中提取文本,但仍然不确定是否是一个好的做法。

提前感谢您!

英文:

I have an app that uses tabbed activity, with 3 tabs, each with a separate fragment and layout. Tab3 has some user-profile settings, like a name for example. Name is displayed inside a cardview, so I made that cardview clickable, and onClick it would open an alertDialog with an edit text to enter the name. to build this dialog I found 2 methods.

First:- (this is run once the cardview is clicked(On clicklistener)) and its working very well and I have no issues with it but it just doesn't feel like a best-practice

AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setTitle("Enter your Username");
LayoutInflater inflater = getActivity().getLayoutInflater();
View view1 = inflater.inflate(R.layout.editname_layout, null);
alert.setView(view1);
final EditText input = view1.findViewById(R.id.editname);
alert.setPositiveButton("Save", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
textView.setText(input.getText().toString());
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Canceled.
}
});
alert.show();

Second:- is that I build a separate DialogFragment with an interface to send data back to fragment this one feels like a best practice but i have faced many issues with it, such as.. when data is sent back to my fragment, I can't use the method "textView.setText" on the received data as I receive it outside the onCreateView method and thus textView always returns null.

public class Dialog extends AppCompatDialogFragment {
private Context context;
public DialogListener listener;
public Dialog(Context context) {
this.context = context;
}
@NonNull
@Override
public android.app.Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.name_layout, null);
final EditText name = (EditText) view.findViewById(R.id.editname);
builder.setView(view)
.setTitle("Username")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String text = name.getText().toString();
listener.data(text);
Toast.makeText(getActivity(), "Saved", Toast.LENGTH_SHORT).show();
}
});
return builder.create();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
Fragment fragment = new Tab3();
listener = (DialogListener) fragment;
}
catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement d.l");
}
}
public interface DialogListener {
void data(String name);
}
}

So what I'm thinking is that I should go with the first method as it's easier, and it's easier to extract text from it but still not sure if it would be a good practice.

thanks in advance!

答案1

得分: 1

这不是最佳实践的问题,而是关乎如何设计你的应用程序。

  • 第一种解决方案:你可以直接与你的用户界面进行交互。例如:在 textView 中设置新值。但是,如果你编写了许多对话框,请考虑将逻辑进行泛化(第二种解决方案)。
  • 第二种解决方案:如果你只想要一个通用的“对话框”,你需要用于它的使用案例,即对话框的多次调用。别忘了:如果你实例化了对话框类,你需要将 textView 传递给它,这样你才能在用户界面中进行更改。
英文:

It's not a question of best practice, it's just how you want to design your App.

  • The first solution: You can directly interact with your UI. e.g: Set the new value in textView. But if you write a lot of dialogs, think about to generify the logic (the second solution).
  • The second solution: If you want just a generic Dialog, you need the use-case for it = multiple calls for dialogs and don't forget: if you instantiate the Dialog class you need to give him the textView if you want to change it in the UI

答案2

得分: 1

优先选择第二种解决方案:

  1. 您可以拥有自己的自定义 UI 元素。
  2. 您可以访问生命周期变化(onResumeonCreate 等等)。
  3. 即使在更改方向时也会保持显示(第一种解决方案不会)。

要将数据发送回上一个片段,您可以创建一个片段listener

interface MyFragmentListener {
    fun onSendBackData(data: Any)
}
class MyFragment : Fragment {
    private var listener: MyFragmentListener? = null
    
    override fun onAttach(context: Context) {
        super.onAttach(context)
        listener = when {
            context is MyFragmentListener -> context
            parentFragment is MyFragmentListener -> parentFragment as MyFragmentListener
            else -> error("You should implement MyFragmentListener")
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        button.setOnClickListener {
            listener?.onSendBackData("Data")
        }
    }
}
class Activity : Activity(), MyFragmentListener {

   override fun onSendBackData(data: Any) {
      textView.text = data.toString()
   }
}
英文:

Prefer second solution:

  1. You can have your custom UI elements.
  2. You have access to lifecycle changes (onResume,onCreate,etc.).
  3. It keeps showing even when orientation is changed (the first solution doesn't).

And for sending data to previous fragment you can create listener to fragment.

interface MyFragmentListener {
fun onSendBackData(data: Any)
}
class MyFragment:Fragment {
private var listener: MyFragmentListener? = null
override fun onAttach(context: Context) {
super.onAttach(context)
listener = when {
context is MyFragmentListener -> context
parentFragment is MyFragmentListener -> parentFragment as MyFragmentListener
else -> error("You should implement MyFragmentListener")
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
button.setOnClickListener {
listener?.onSendBackData("Data")
}
}
}
class Activity : Activity(), MyFragmentListener {
override fun onSendBackData(data:Any) {
textView.text = data.toString()
}
}
</details>

huangapple
  • 本文由 发表于 2020年10月17日 20:10:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/64402299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定