ืืืจ ืืึธืื ืืืจ ืืื ืฆื ืฉืึทืคึฟื ืึท ืคึผืฉืื ืึทืคึผืืึทืงืืืฉืึทื ืคึฟืึทืจ ืงืึทืืงืืึทืืืืืื ื ืขืฆืืช ืืื ืงืึธืืืื. ืืขืจ ืืขื ืื, ืงืึธืืืื 1.3.21, ืึทื ืืจืืื 4, ืึทื ืืจืืื ืกืืืืืึธ 3. ืืขืจ ืึทืจืืืงื ืืืขื ืืืื ืืฉืืงืึทืืืข, ืขืจืฉืืขืจ ืคืื ืึทืืข, ืคึฟืึทืจ ืื ืืืืก ืืขื ืขื ืกืืึทืจืืื ื ืืืืขืจ ื ืกืืขื ืืื ืึทื ืืจืืื ืึทืคึผืืึทืงืืืฉืึทื ืึทื ืืืืืงืืื ื. ืขืก ืึทืืึทืื ืืืจ ืฆื ืคึฟืึทืจืฉืืืื ืืืึธืก ืืื ืืื ืขืก ืึทืจืืขื ืืื ืื ืึทืคึผืืึทืงืืืฉืึทื.
ืืขืจ ืงืึทืืงืืืึทืืึธืจ ืืืขื ืืืื ื ืืฆืืง ืืืขื ืืืจ ืืึทืจืคึฟื ืฆื ืจืขืืขื ืขื ืื ืกืืืข ืคืื โโืขืฆืืช ืคืื ืึท ืคืืจืืข ืืืึธืก ืืึทืฉืืึธืกื ืฆื ืคืึทืจืืจืขื ืืขื ืฆืืื ืืื ืึท ืจืขืกืืึธืจืึทื ืึธืืขืจ ืงืึทืคืข. ืคึฟืึทืจืฉืืืื ืืื, ืึทื ื ืื ืึทืืข ืืึธืื ืึทืืขืืึธื ืึท ืฉืคึผืืฅ ืคึฟืึทืจ ืื ืงืขืื ืขืจืก, ืืึธืก ืืื ืืขืจ ืึท ืืขืจืืืืงืข ืืจืึทืืืฆืืข, ืึธืืขืจ ืืขืจ ืคึผืจืึธืฆืขืก ืคึฟืื ืึทื ืืืืืงืืขื ืึทืืึท ืึทืคึผืคึผืืืงืึทืฆืืข ืืื ืืืืื ืืื ืืขืจืขืกืึทื ื;
ืืืจ ืืขืจืืึธื ืขื ืืืจ: ืคึฟืึทืจ ืึทืืข ืืืืขื ืขืจ ืคืื "ืืืจ" - ืึท ืึทืจืึธืคึผืจืขืืขื ืขื ืคืื 10 ืจืืื ืืืขื ืืืจ ืคืึทืจืฉืจืืึทืื ืืื ืงืืื ืกืงืืืืึธืงืก ืงืืจืก ื ืืฆื ืื ืคึผืขืจืืึธืืฉืึทื ืึทื ืงืึธื "ืืืจ".
Skillbox ืจืขืงืึทืืขื ืื: ืคึผืจืึทืงืืืฉ ืงืืจืก
"ืืึธืืื ืืขืืืขืืึธืคึผืขืจ PRO .
ืืึธืก ืืื ืืื ืื ืึทืคึผืืึทืงืืืฉืึทื ืงืืงื ืืื ืืื ืึธืคึผืขืจืึทืฆืืข:
ืืืจ ืึทืจืืึทื ืื ืืขืืืืื ืคึผืจืึธืฆืขื ื ืคืื ืื ืืึทื ืฅ ืกืืืข, ืื ื ืืืขืจ ืคืื ืืึทืืขืืขื ืืฉ ืคึผืึทืจืืืกืึทืคึผืึทื ืฅ, ืืื ืืึทืงืืืขื ืื ืจืขืืืืืึทื - ืื ืกืืืข ืคืื โโืฉืคึผืืฅ ืืืจ ืืึธื ืืึธืื.
ืืขืืื ื ืกืืึทืจืืขื
ืื ืืึทื ืฅ ืึทืคึผืืึทืงืืืฉืึทื ืฆืืืื ื ืงืืงื ืืื ืืึธืก:
ืขืจืฉืืขืจ ืงืึทืืฃ -
ืืึทื ืืฆืขืจ ืึทืงืฉืึทื ื ืืขื ืขื ืืขืฉืจืืื ืืื ืื ืคึผืจืืืขืงื ืืื ืงืจืึทื ืึทืืึทืืืฉืืงืึทื ืกืืจ ืฆื ืืึทืื ืึทืืฅ ืงืืึธืจ. ืฆื ืืขื ืขืก, ืขืคืขื ืขื View -> Tool Windows -> TODO.
ืืืจ ืืขืจื ืขื ืื ืคึผืจืืืขืงื ืืื ืขืคืขื ืขื ืงืึธืืึธืจืก.ืงืกืื ืฆื ืึธืคึผืฉืึทืฆื ืื ืงืึธืืืจ ืคึผืึทืืืืจืข. strings.xml ืึผืืื ืืขืงืกื ืืึทืื (ืกืืื ืึทืืฉืขืจื), ืืื styles.xml ืึผืืื ืขืืืขืืข ืฉืจืืคึฟื ืืขืืคึผืืึทืืขืก.
ืคึผืจืืึทื ืึธืคึผืืืืืื ื ืึทื ืืืืืงืืื ื
ืขืคึฟืขื ืขื Activity_main.xml ืืื ืืืื ืืขื ืงืึธื ืืื ืื ืฆื ืื LinearLayout (#1):
<TextView
android_id="@+id/expensePerPersonTextView"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_paddingTop="30dp"
style="@style/h1Bold"
android_textColor="@color/colorAccent"
android_text="0"/>
<TextView
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_paddingBottom="25dp"
style="@style/h2"
android_textColor="@color/colorAccent"
android_text="@string/perPersonStaticText"/>
ืืืฆื ืืืจ ืงืขื ืขื ืกืืื ืื ืืืึทืืืขืก ืืืขืืืืืึทืืขืจ ืึธืืขืจ ืฉืคึผืืื ืืื ืคืืจืื ื ืืฆื
ืืืฆื ืื ืคึผืจืืืขืงื ืงืืงื ืืื ืืึธืก:
ืืื ืืืจ ืงืขื ืขื ืืขื, ืงืึธืก ืืขื ืขื ืงืึทืืงืืึทืืืืืื ืืืืืจื ืืืืฃ ืื ืืึทืื ืืจืืื ืืืจื ืื ืืึทื ืืฆืขืจ.
ืึทื ืืืืืงืืื ื ืคืื ืื ืึทืงืึทืื ืฅ ืึธืคึผืืืืืื ื
ืืืื ืืขื ืงืึธื ืืื ืื ืฆื ืื ืืื ืขืึทืจ ืืืึทืึทืื ื ืึธื ืื ืงืึธืกื ืึธืคึผืืืืืื ื (#2):
<LinearLayout
android_layout_width="match_parent"
android_layout_height="match_parent"
android_orientation="vertical"
android_background="@color/colorAccent">
<! โ TODO #3: Build Bill Section โ
โฆ
</LinearLayout>
ืืืจ ืคืึทืจืืึทืื ืื ืืื ืขืึทืจ ืืืึทืึทืื ื ืึธื ืื ืจืฉืืื ืคืื ืืึธืืึธ, ืืื ืืขืจืืืขืจ ืืืืื ื ืืึท ืงืึธื, ืคึผืืืืกืื ื ืขืก ืืื ืื ืืื ืขืึทืจ ืืืึทืึทืื (#3):
<TextView
android_layout_margin="15dp"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textColor="@color/colorWhite"
style="@style/h4"
android_text="@string/billStaticText"/>
<EditText
android_id="@+id/billEditText"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textColor="@color/colorWhite"
android_inputType="numberDecimal"
android_maxLines="1"
style="@style/h2Bold"
android_text="0"/>
ืืื ื ืื ืืืืคึผื ืึทืจืืขื ืคืื ืื ืึทืคึผืืึทืงืืืฉืึทื ืืื ืฆื ืจืขืืขื ืขื ืืืื ืงืึธืก ืคึฟืึทืจ ืืขืืขืจ ืืึทืืืืืืงืืขืจ ืืื ืึท ืจืขืกืืึธืจืึทื ืฆืื ืืืคืงืื, ืงืึธืก ืคึผืขืจืคึผืขืจืกืึธื ืืขืงืกืืืืืขืื ืคืืขืกืขืก ืื ืืืืคึผื ืจืึธืืข.
ืขืืืืืขืงืกื ืืืืึทืฅ ืื ืึทืจืืึทื ืฉืจืืึทื ืฆื ืืืื ืฉืืจื, ืืขื ืคึผืึทืจืึทืืขืืขืจ ืืืื ืืืื ืฉืืขืื ืฆื NumberDecimal inputType.
ืืืจ ืงืึทืืขืจ ืื ืคึผืจืืืขืงื ืคึฟืึทืจ ืื ืคึผืจืึธืืข ืืื ืึทืจืืึทื ืื ืคึผืึทืจืึทืืขืืขืจืก ืคึฟืึทืจ ืืขื ืขืจืึทื ืฉืขืืืงื (ืฆืขืืจืืื ืืขืคึผืืขื, ืคึผืืึทืืขืก, ืืื"ื ื)
ืึทื ืืืืืงืืื ื ืคืื ืื "ืืขื ืืฉื ืืื ืขืฆืืช" ืึธืคึผืืืืืื ื
ืฆื ืืืืื ืึท ืฉืคึผืืฅ ืืึทื ื ืกืขืืขืงืฆืืข, ืคึผืึทืคึผ ืื ืงืึธื ืืื ืื ืืื ืื ื ืืึทืข LinearLayout ืึธืคึผืืืืืื ื (#4):
<TextView
android_layout_margin="15dp"
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_textColor="@color/colorWhite"
style="@style/h4"
android_text="@string/tipStaticText"/>
<LinearLayout
android_layout_width="match_parent"
android_layout_height="wrap_content"
android_orientation="horizontal">
<ImageButton
android_id="@+id/subtractTipButton"
style="@style/operationButton"
android_layout_marginLeft="20dp"
android_layout_marginStart="20dp"
android_src="@drawable/subtract"/>
<TextView
android_id="@+id/tipTextView"
android_layout_margin="15dp"
android_layout_width="0dp"
android_layout_height="wrap_content"
android_textColor="@color/colorWhite"
android_layout_weight="1"
style="@style/h2Bold"
android_text="20%"/>
<ImageButton
android_id="@+id/addTipButton"
style="@style/operationButton"
android_layout_marginEnd="20dp"
android_layout_marginRight="20dp"
android_src="@drawable/add"/>
</LinearLayout>
ืืขื ืึธืคึผืืืืืื ื ืคืื ืงืึธื ืืื ื ืืืืืง ืฆื ืึทืงืืขืจืึทืืื ืจืขืืขื ืขื ืื ืฉืคึผืืฅ ืกืืืข. ืื ืคืขืืืงืืึทื ืืขืงืกื ืืืขืจื ืืื 20. ImageButtons ืืขื ืขื ืฆืืืขืฉืืขืื ืืื ืืืงืึทื ื ืืื ืึท ืืขืงืข ืืื ืฉืจืืึทืื ืคึผืขืจืืืฉืึทื ื.
ืงืึธืคึผื ืื ืึธืคึผืืืืืื ื ืืึธืจ ืืื ืืืืื ืื ืคืืืืขื ืืข (#5):
- ImageButton ืืืก (subtractPeopleButton, addPeopleButton)
- TextView ids (ื ืืืขืจ ืคืื ืืขื ืืฉื ืกืืึทืืืง ืืขืงืกื, ื ืืืขืจ ืคืื ืืขื ืืฉื ืืขืงืกืืืืืขืื)
- DefaultText ืคึฟืึทืจ NumberOfPeopleTextView (ืืืื ืืืื 4).
ืืืฆื, ืืืขื ืืืจ ืงืึทืืขืจ ืื ืึทืคึผืืึทืงืืืฉืึทื, ืขืก ืืื ืึท ืืขืืขืื ืืืื ืฆื ืืืืื ืื ืื ืืืืืก ืกืืืข, ืื "ืืืื / ืึทืจืึธืคึผืจืขืืขื ืขื" ืงื ืขืคึผืืขื ืืืื ืึทืจืืขื, ืึธืืขืจ ืืึธืจื ืืฉื ืืึทืคึผืึทื ื ื ืึธื.
ืึทืืื ื ืงืืงื
ืขืคึฟืขื ืขื MainActivity.kt ืืื ืืืื ืืึธืก ืฆื ืื initViews ืคืื ืงืฆืืข (#6):
private fun initViews() {
expensePerPersonTextView = findViewById(R.id.expensePerPersonTextView)
billEditText = findViewById(R.id.billEditText)
addTipButton = findViewById(R.id.addTipButton)
tipTextView = findViewById(R.id.tipTextView)
subtractTipButton = findViewById(R.id.subtractTipButton)
addPeopleButton = findViewById(R.id.addPeopleButton)
numberOfPeopleTextView = findViewById(R.id.numberOfPeopleTextView)
subtractPeopleButton = findViewById(R.id.subtractPeopleButton)
//TODO #8: Bind Buttons to Listener
//TODO #16: Bind EditText to TextWatcher
}
ืคืื ืืฉืื ื ืื ืงื ืขืคึผืืขื
ืฆื ืืืืื ืฉืืืฆื ืคึฟืึทืจ ืงื ืขืคึผื ืงืืืงืก, ืืืจ ืื ืกืืจืืืขื ื View.OnClickListener ืืื ืื ืงืืึทืก ืืืจืื (#7):
ืงืืึทืก MainActivity: AppCompatActivity(), View.OnClickListener {
ืขืก ืืืขื ื ืื ืืืื ืืขืืืขื ืฆื ืืึทืืืขื ืื ืคึผืจืืืขืงื ืจืขืื ืืืฆื, ืืืจ ืืึทืจืคึฟื ืฆื ืืืจืืคืืจื ืึท ืืืกื ืืขืจ ืกืืขืคึผืก (#8):
override fun onClick(v: View?) {
when (v?.id) {
R.id.addTipButton -> incrementTip()
R.id.subtractTipButton -> decrementTip()
R.id.addPeopleButton -> incrementPeople()
R.id.subtractPeopleButton -> decrementPeople()
}
}
ืืื ืืขืจืืื ืขื ืคืื ืงื ืขืคึผืืขื ืืื ืกืืืืืฉืื, ืงืึธืืืื ืึธืจืืึทื ืืืืจื ืึทืืฅ ืืืืขืจ ืงืื! ืืืื ืื ืงืึธื ืืื ืื ืฆื ืึทืืข ืื ืงืจืึทืืึทื ื ืืื ืืขืงืจืขืืขื ื ืคืึทื ืืงืฉืึทื ื
(#9 - #12):
private fun incrementTip() {
if (tipPercent != MAX_TIP) {
tipPercent += TIP_INCREMENT_PERCENT
tipTextView.text = String.format("%d%%", tipPercent)
}
}
private fun decrementTip() {
if (tipPercent != MIN_TIP) {
tipPercent -= TIP_INCREMENT_PERCENT
tipTextView.text = String.format("%d%%", tipPercent)
}
}
private fun incrementPeople() {
if (numberOfPeople != MAX_PEOPLE) {
numberOfPeople += PEOPLE_INCREMENT_VALUE
numberOfPeopleTextView.text = numberOfPeople.toString()
}
}
private fun decrementPeople() {
if (numberOfPeople != MIN_PEOPLE) {
numberOfPeople -= PEOPLE_INCREMENT_VALUE
numberOfPeopleTextView.text = numberOfPeople.toString()
}
}
ืืึธ ืื ืงืึธื ืคึผืจืึทืืขืงืฅ ืื ืื ืงืจืึทืืึทื ื ืคืึทื ืืงืฉืึทื ื ืืื ืืึทืงืกืืืื ืืืึทืืืขืก (MAX_TIP & MAX_PEOPLE). ืึทืืืืืืึธื ืึทืืื, ืืขืจ ืงืึธื ืคึผืจืึทืืขืงืฅ ืื ืืขืงืจืขืืขื ื ืคืึทื ืืงืฉืึทื ื ืืื ืืื ืืืื ืืืึทืืืขืก (MIN_TIP & MIN_PEOPLE).
ืืืฆื ืืืจ ืคืึทืจืืื ืื ืื ืงื ืขืคึผืืขื ืืื ืฆืืืขืจืขืจืก ืืื ืื initViews ืคืื ืงืฆืืข (#13):
private fun initViews() {
...
addTipButton.setOnClickListener(this)
subtractTipButton.setOnClickListener(this)
addPeopleButton.setOnClickListener(this)
subtractPeopleButton.setOnClickListener(this)
//TODO #15: Bind EditText to TextWatcher
}
ืืืจ ืงืขื ื ืืืฆื ืืืืื ืืึทื ืฅ ืืึทืืืืืฉืื, ืขืฆืืช ืืื ืื ื ืืืขืจ ืคืื ืืึทืืขืืขื ืืฉ ืคึผืึทืจืืืกืึทืคึผืึทื ืฅ. ื ื, ืืืฆื ืื ืืขืจืกื ืืืืืืืง ืืึทื ...
ืคึผืจืืึทื ืืขืืฉืื ืึธืคึผืืืืืื ื
ืืขืจ ืงืึธื ืงืึทืืงืืึทืืืืฅ ืงืึธืก (#14):
private fun calculateExpense() {
val totalBill = billEditText.text.toString().toDouble()
val totalExpense = ((HUNDRED_PERCENT + tipPercent) / HUNDRED_PERCENT) * totalBill
val individualExpense = totalExpense / numberOfPeople
expensePerPersonTextView.text = String.format("$%.2f", individualExpense)
}
ื ื, ืืึธ ืืื ืืขืจืืคื ืึท ืคึฟืื ืงืฆืืข ืืืึธืก ืืืื ืขืก ืืขืืืขื ืฆื ื ืขืืขื ืืื ืืฉืืื ืื ื ืืืขืจ ืคืื ืืขื ืืฉื ืืื ืื ืคืืจืืข ืืื ืจืขืืขื ืขื ืขืฆืืช (#15):
private fun incrementTip() {
โฆ
}
private fun decrementTip() {
โฆ
}
private fun incrementPeople() {
โฆ
}
private fun decrementPeople() {
โฆ
}
ืืื ืก ืงืึทืืขืจ ืื ืึทืคึผืืึทืงืืืฉืึทื. ืขืก ืงืืงื ืืื ืึทืจืืขื ืืจืืืก. ืืืขืจ ืขืก ืงืขื ืืืื ืืขืกืขืจ.
ืืืื ืืืจ ืคึผืจืืืืจื ืฆื ืืึทืืืึทืืืงื ืื ืจืขืืขื ืื ื ืกืืืข ืืื ืืขืจื ืึธื ืคืึทืจืืจืขืกืขืจื ืื ื ืืืขืจ ืคืื ืืจืื ืงืืขืื ืึธืืขืจ ืคืจืขื ืื, ืื ืึทืคึผืืึทืงืืืฉืึทื ืืืขื ืงืจืึทื ืืืืึทื ืขืก ืืื ื ืึธื ืงืืื ืืฉืขืง ืคึฟืึทืจ ืื ื ืื ืคึผืจืืึทื ืืืขืจื. ืืขืจืฆื, ืืืื ืืืจ ืคึผืจืืืืจื ืฆื ืืืืฉื ืื ืจืขืืขื ืื ื ืกืืืข, ืื ืืฉืึทืจืืืฉืื ืืืขื ื ืืฉื ืืืื ืืขืจืืืึทื ืืืงื.
ืืขืฆื ืืจืื
ืืืื ืืขืงืกืืืืึทืืฉืขืจ (#16):
ืงืืึทืก MainActivity: AppCompatActivity(), View.OnClickListener, TextWatcher {
ืืขืจื ืึธื ืืืจ ืืืืขื ืื ืืืืขืืืืืขืงืกื ืืืกื ืขืจ (#17):
billEditText.addTextChangedListener(ืืขื)
ืคึผืืืก ืืืจ ืืืืื ืงืึธื ืฆื ืืืกืคืืจื ืืขืงืกืืืืึทืืฉืขืจ (#18):
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (!billEditText.text.isEmpty()) {
calculateExpense()
}
}
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
ื ื, ืืืฆื ืืขืืึทืืจืข ืึทืืฅ ืึทืจืืขื! ืืึทืื - ืืึธืื, ืืืจ ืืึธื ืืขืฉืจืืื ืืืื ืืืืืขื ืข "ืฉืคึผืืฅ ืงืึทืืงืืืึทืืึธืจ" ืืื ืงืึธืืืื.
Skillbox ืจืขืงืึทืืขื ืื:
- ืฆืืืื-ืืึธืจ ืคึผืจืึทืงืืืฉ ืงืืจืก
"ืืื ืืื ืึท ืืืขื ืืขืืืขืืึธืคึผืขืจ ืคึผืจืึธ" .- ืึธื ืืืื ืงืืจืก
"C# ืืขืืืขืืึธืคึผืขืจ" .- ืคึผืจืึทืงืืืฉ ืืึธืจ ืงืืจืก
"PHP ืืขืืืขืืึธืคึผืขืจ ืคึฟืื 0 ืฆื ืคึผืจืึธ" .
ืืงืืจ: www.habr.com