我制作了一个非常基本的加权平均计算器,作为Android应用程序(Java),它运行良好。
用户只需在三个a
中输入3个值b
,c
,EditText
,然后计算公式:
d = 0.25 * a + 0.25 * b + 0.5 * c;
此数学方程式的结果显示在TextView
中,所有这些都在按下按钮的情况下显示在MainActivity
中。
但是在创建一个新的项目以获得更好的UI(使用Android Studio模板导航抽屉活动)后,我意识到我的代码无法正常工作。
我如何修改该计算器以在片段(名为CalculatorWeightedFragment
)中获取输入以进行计算并在按下按钮时在同一片段的TextView中显示结果?
至此,我得到的只是静态内容的显示,而没有为按钮分配任何操作。
代码如下:
CalculatorWeightedFragment.java
public class CalculatorWeightedFragment extends Fragment {
private CalculatorWeightedViewModel calculatorWeightedViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
calculatorWeightedViewModel =
ViewModelProviders.of(this).get(calculatorWeightedViewModel.class);
View root = inflater.inflate(R.layout.fragment_calculator_w, container, false);
final TextView textView = root.findViewById(R.id.id_result); // result d stored in id_result
calculatorWeightedViewModel.takeText().observe(getViewLifecycleOwner(),
new Observer<String>() {
@Override
public void onChanged(@Nullable String str) {
textView.setText(str);
}
});
return root;
}
}
CalculatorWeightedViewModel.java
public class CalculatorWeightedViewModel extends ViewModel {
private MutableLiveData<String> testString;
public CalculatorWeightedViewModel() {
testString = new MutableLiveData<>();
testString.setValue("" + 0.5);
}
public LiveData<String> takeText() {
return testString;
}
}
基于您的xml布局内容:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/id_a"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/id_b"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/id_c"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/id_buton_rata"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="calculateFunction" />
<TextView
android:id="@+id/id_result"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
LiveData
和ViewModel
)我创建了一些新的简单片段(例如)
public class CalculatorWeightedFragment extends Fragment {
private Button button;
private EditText editTextA;
private EditText editTextB;
private EditText editTextC;
private TextView textViewD;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_calculator_w, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
button = view.findViewById(R.id.id_buton_rata);
editTextA = view.findViewById(R.id.id_a);
editTextB = view.findViewById(R.id.id_b);
editTextC = view.findViewById(R.id.id_c);
textViewD = view.findViewById(R.id.id_result);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
double result = calculateResult();
String output = String.format("Result: %s", result);
textViewD.setText(output);
}
});
}
private double calculateResult() {
try {
int a = Integer.parseInt(editTextA.getText().toString());
int b = Integer.parseInt(editTextB.getText().toString());
int c = Integer.parseInt(editTextC.getText().toString());
// Result
return 0.25 * a + 0.25 * b + 0.5 * c;
} catch (NumberFormatException e) {
e.printStackTrace();
return 0;
}
}
}
LiveData
和ViewModel
)[使用LiveData
和ViewModel
时,不需要Fragment
中的按钮。您可以观察所有更改。
您在创建此片段的活动。要在Fragment中使用ViewModel,您可以使用依赖项注入(例如,使用Dagger库)或从ViewModelProviders
(或AndroidViewModelFactory
)获取它。
在这里,为了使示例尽可能简单,我通过构造函数传递了它。
活动
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CalculatorWeightedViewModel vm = new CalculatorWeightedViewModel();
CalculatorWeightedFragment fragment = new CalculatorWeightedFragment(vm);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.frame_layout, fragment);
transaction.commit();
}
}
ViewModel
您可以将值(a
,b
,c
)存储为不同目的的字段。在这里,我正在重新计算实时结果,没有任何多余的内容。为了使其尽可能简单。
package com.example.stack_android;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class CalculatorWeightedViewModel extends ViewModel {
private MutableLiveData<String> testString = new MutableLiveData<>();
public LiveData<String> takeText() {
return testString;
}
void updateValues(double a, double b, double c) {
double result = recalculate(a, b, c);
String value = "Result: " + result;
testString.postValue(value);
}
void showError() {
testString.postValue("Wrong Value");
}
private double recalculate(double a, double b, double c) {
return 0.25 * a + 0.25 * b + 0.5 * c;
}
}
片段:
此外,您可以为每个字段创建单独的侦听器。在这里,我为所有字段都使用一个(名为TextWatcher listener
)。
public class CalculatorWeightedFragment extends Fragment {
private CalculatorWeightedViewModel viewModel;
private EditText editTextA;
private EditText editTextB;
private EditText editTextC;
private TextView textViewD;
public CalculatorWeightedFragment(CalculatorWeightedViewModel viewModel) {
this.viewModel = viewModel;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_calculator_w, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
editTextA = view.findViewById(R.id.id_a);
editTextB = view.findViewById(R.id.id_b);
editTextC = view.findViewById(R.id.id_c);
textViewD = view.findViewById(R.id.id_result);
TextWatcher listener = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
textChanged();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Not used
}
@Override
public void afterTextChanged(Editable s) {
// Not used
}
};
editTextA.addTextChangedListener(listener);
editTextB.addTextChangedListener(listener);
editTextC.addTextChangedListener(listener);
viewModel.takeText().observe(getViewLifecycleOwner(), new Observer<String>() {
@Override
public void onChanged(String newValue) {
textViewD.setText(newValue);
}
});
}
private void textChanged() {
try {
int a = Integer.parseInt(editTextA.getText().toString());
int b = Integer.parseInt(editTextB.getText().toString());
int c = Integer.parseInt(editTextC.getText().toString());
viewModel.updateValues(a, b, c);
} catch (NumberFormatException e) {
viewModel.showError();
e.printStackTrace();
}
}
}
它应该在那里工作: