рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐
рдмрдзрд╛рдИ, рд╕рд╣рдХрд░реНрдорд┐рдпреЛрдВ!
рдмрд╣реБрдд рдмрд╛рд░, рдЬрдм рдорд▓реНрдЯреАрдореАрдбрд┐рдпрд╛ рдПрдВрдбреНрд░реЙрдЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдЗрд╕рдХреЗ рдмрд╛рдж рдмрд╕ "рдПрдкреНрд▓рд┐рдХреЗрд╢рди"), рддреЛ рд╣рдореЗрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдШрдЯрдХреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ рдЬреЛ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рдпрд╣ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕реНрд╡рд┐рдЪ рдиреЙрдмреНрд╕, рд╕реНрдкреЗрдХреНрдЯреНрд░рдо рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝рд░, рдЖрджрд┐ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдЙрдирдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЛ рдмрд╕ рдЧреНрд░рд╛рдлрд┐рдХ рд╕рдВрд╕рд╛рдзрди рдХреА рдЬрдЧрд╣, рдХреИрдирд╡рд╛рд╕ рдХреЛ 90 рдбрд┐рдЧреНрд░реА рдкрд░ рдШреБрдорд╛рдХрд░ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди, рдХрднреА-рдХрднреА, рдЖрдкрдХреЛ рдЕрднреА рднреА рдХреБрдЫ рдЕрд▓рдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ "рдХреЗ рд╕рд╛рде" рд╢реВрдиреНрдпред тАЭ
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдПрдХ рдШрдЯрдХ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ - рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкрд┐рдпрд╛рдиреЛ рдХреАрдмреЛрд░реНрдб, рд╡реНрдпреВ рдХреНрд▓рд╛рд╕ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдФрд░ рд╕рднреА рдЖрдВрддрд░рд┐рдХ "рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ" рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрдиреЛрдВ рдореЗрдВ рдХреНрдпреЛрдВ - рдЖрдЧреЗ рджреЗрдЦреЗрдВред
рд▓реЗрдЦреЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рдореИрдВ рдЗрд╕ рддрд░рд╣ рдХреЗ рдореБрджреНрджреЛрдВ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛:
- рдШрдЯрдХ рдкреНрд░рддрд┐рдкрд╛рджрди
- рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдорд╛рдирдХ рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛
- рдмрд╛рддрдЪреАрдд, рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рдЪрдпрдирдХрд░реНрддрд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
- рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рддреЗ рд╕рдордп рдШрдЯрдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реЗрдЬрдирд╛
- рдУрд╡рд░рдХреНрд░реЛрд▓ рдХреЗ рд▓рд┐рдП рдмреИрдХрд▓рд╛рдЗрдЯ рдЬреЛрдбрд╝рдирд╛
- рдПрдХреНрд╕рдПрдордПрд▓ рдХреЛ рдкрд╛рд╕рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░
- рдЪреБрдЯрдХреА рдореЗрдВ рдЭреВрдордирд╛
рдкрд╣рд▓рд╛ рд▓реЗрдЦ рдкрд╣рд▓реЗ рддреАрди рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реЛрдЧрд╛ред
рдпрджрд┐ рдЖрдк рдЗрди рд╡рд┐рд╖рдпреЛрдВ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рддреЛ рдмрд┐рд▓реНрд▓реА рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИред
рдкреНрд░рд╛рдЧрд┐рддрд┐рд╣рд╛рд╕
рдПрдХ рдмрд╛рд░, рдЬрдм рдореИрдВрдиреЗ рдЕрдкрдирд╛ рд╕рдВрдЧреАрдд рдРрдк рд▓рд┐рдЦрд╛ рдерд╛, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦреЛрдВ рдореЗрдВ рдмрд╛рдд рдХреА рдереА, рддреЛ рдореБрдЭреЗ рдкрд┐рдпрд╛рдиреЛ рдХреЛ рдХрд╛рдЯрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рдерд╛ред рдЪреВрдВрдХрд┐ рдпрд╣ рдореЗрд░рд╛ рдкрд╣рд▓рд╛ рдПрдВрдбреНрд░реЙрдЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдерд╛, рдФрд░ рдПрдВрдбреНрд░реЙрдЗрдб рддрдм рдмрд┐рд▓реНрдХреБрд▓ рднреА рд╡реИрд╕рд╛ рдирд╣реАрдВ рдерд╛ рдЬреИрд╕рд╛ рдХрд┐ рдЕрдм рд╣реИ, рдкрд╣рд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрдо рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдШрдЯрдХ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рд╡рд┐рдХреГрддрд┐ рдмрдирд╛рдИред рдореИрдВ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рдмрд┐рдЯрдореИрдк рдХреЛ рдпрд╛рдж рдореЗрдВ рд░рдЦрддрд╛ рдерд╛, рдПрдХ рдСрдХреНрдЯреЗрд╡ рдХреЗ рд╕рд╛рде 4 рдЫрд╡рд┐рдпреЛрдВ рд╕реЗ рдПрдХ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рдерд╛, рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдЕрд▓рдЧ рд╕реНрдЯреНрд░реАрдо рдерд╛ рдЬреЛ рдХрд┐ рджрд┐рдП рдЧрдП рдЕрдВрддрд░рд╛рд▓ рдкрд░ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХреА рдЧрддрд┐ рдХреЛ рдХрдо рдХрд░ рджреЗрддрд╛ рдерд╛ рдФрд░ рдЕрдЧрд▓реЗ рдХрд╛рд░реНрдп рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рддрдХ рд╕реЛ рдЬрд╛рддрд╛ рдерд╛ред рдЕрдиреНрддрд░рдХреНрд░рд┐рдпрд╛рд╢реАрд▓рддрд╛ рд╢реВрдиреНрдп рдереАред
рдЕрдм, рдХреБрдЫ рд╕рдордп рдмрд╛рдж, рдореИрдВ рдЕрдкрдиреЗ рдкрд╣рд▓реЗ рдХреЗ рд╕рдорд╛рди рдХрдИ рддрд░реАрдХреЛрдВ рд╕реЗ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд▓рд┐рдЦ тАЛтАЛрд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЧреБрдгрд╡рддреНрддрд╛ рдФрд░ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╕реНрддрд░ рдкрд░, рдФрд░ рдлрд┐рд░ рд╕реЗ рдореБрдЭреЗ рдПрдХ рдкрд┐рдпрд╛рдиреЛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╡рд╣реА рдореИрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ред
рдШрдЯрдХ рд╡рд┐рдХрд╛рд╕
рджреЗрдЦреЗрдВ рдпрд╛ рд╕рд░рдлреЗрд╕рд╡реНрдпреВ?
рдЕрдВрдЧреВрдареЗ рдХрд╛ рдирд┐рдпрдо, рдЬрд┐рд╕реЗ рдореИрдВ рдЦреБрдж рдХреЗ рд▓рд┐рдП рд▓рд╛рдпрд╛ рдерд╛, рдЬрд╣рд╛рдВ рднреА рд╕рдВрднрд╡ рд╣реЛ, рд╡реНрдпреВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдФрд░ рд╕рд░реНрдлреЗрд╕ рд╡реНрдпреВ рд╕реЗ рдмрдЪреЗрдВ рдЬрдм рддрдХ рдХрд┐ рдЖрдкрдХреЛ рдПрдХ рдШрдЯрдХ рди рд╣реЛ рдЬреЛ рд▓рдЧрд╛рддрд╛рд░ рдХрдо рдпрд╛ рдЬреНрдпрд╛рджрд╛ рдЬрдЯрд┐рд▓ рдЧреНрд░рд╛рдлрд┐рдХреНрд╕ (рдЧреЗрдо, рд╡реАрдбрд┐рдпреЛ) рдХреЗ рд╕рд╛рде рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рдмрджрд▓рддреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЕрдиреНрдп рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рджреГрд╢реНрдп рдЖрдкрдХреА рдкрд╕рдВрдж рд╣реИред рдЖрдкрдХреЛ рдпрд╣ рднреА рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рднреВрддрд▓ рд╡реНрдпреВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдо рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЖрдкрдХреЗ рд▓реЗрдЖрдЙрдЯ рдореЗрдВ рдЗрд╕ рдШрдЯрдХ рдХреЛ рдЪреЗрддрди рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдЦреЛ рджреЗрддреЗ рд╣реИрдВред
рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЪрд░рдг
рддреЛ, рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рдкрд╣рд▓реА рдмрд╛рдд рдЬреЛ рд╣рдо рдХрд░реЗрдВрдЧреЗ рд╡рд╣ рд╣реИ рдПрдХ рдирдпрд╛ рд╡рд░реНрдЧ, android.view.View рдХрд╛ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реАред рдЗрд╕реЗ PianoView рдХрд╣рддреЗ рд╣реИрдВред
public class PianoView extends View { public PianoView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдПрдХ рд╕рдВрджрд░реНрдн рдФрд░ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдПрдХ рд╕реЗрдЯ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдСрдирдбреНрд░рд╛рдЗрд╡ рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдШрдЯрдХ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░реЗрдВрдЧреЗред рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рд╣рд░ рдмрд╛рд░ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рджреГрд╢реНрдп рдХреЛ рдлрд┐рд░ рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдиреАрдореЗрд╢рди рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдлреНрд░реЗрдо рдХреЗ рд▓рд┐рдПред
рдХреАрдмреЛрд░реНрдб рд░реЗрдВрдбрд░рд┐рдВрдЧред рдЧреНрд░рд╛рдлрд┐рдХ рд╕рдВрд╕рд╛рдзрдиред
рдЪрд╛рдмрд┐рдпрд╛рдБ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдорд╛рдирдХ рдПрдВрдбреНрд░реЙрдЗрдб рдЯреВрд▓реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛: рдЪрдпрдирдХрд░реНрддрд╛, рдиреМ-рдкреИрдЪ рдбреНрд░реЙрдПрдмрд▓ред
рд╕рдлреЗрдж рдХреБрдВрдЬреА рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд 9-рдкреИрдЪ рдЪрд┐рддреНрд░ рддреИрдпрд╛рд░ рдХрд┐рдПред рдореИрдВрдиреЗ рд╣реЛрд▓реЛ рдХреЗ рд▓рд┐рдП рдорд╛рдирдХ рдиреАрд▓реА рдмреИрдХрд▓рд╛рдЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╣рд╛рдЗрд▓рд╛рдЗрдЯреЗрдб рд░рд╛рдЬреНрдп рдмрдирд╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред


рдХрд╛рд▓реЗ рд░рдВрдЧ рдХреЗ рд▓рд┐рдП:


рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рдЪрдпрдирдХрд░реНрддрд╛ рдмрдирд╛рдпрд╛:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/white_key_pressed" android:state_pressed="true"></item> <item android:drawable="@drawable/white_key"></item> </selector>
рдЕрдм рдЬреЛ рдХреБрдЫ рдмрдЪрд╛ рд╣реИ, рдЙрд╕реЗ рдпреЗ рдбреНрд░реЙрдмрд▓реНрд╕
context.getResourses.getDrawable();
рд▓рд┐рдП рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИ редgetResourses.getDrawable
context.getResourses.getDrawable();
рдХреАрдмреЛрд░реНрдб рд░реЗрдВрдбрд░рд┐рдВрдЧред рдХреЛрдб
рдЗрд╕рд▓рд┐рдП, рдШрдЯрдХ рдХреЛрдб рдХреЛ рд╕рд╛рдл рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рднреА рдХреБрдВрдЬреАрдкрдЯрд▓ рд░реЗрдВрдбрд░рд┐рдВрдЧ рдХреЛ рдирд┐рдХрд╛рд▓ рд▓рд┐рдпрд╛ рдФрд░ рдХреАрдмреЛрд░реНрдб рд╡рд░реНрдЧ рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХреАред рд╣рдорд╛рд░реЗ
onDraw
рдореИрдВ рдмрд╕ рдЗрд╕рдХреА рд╡рд┐рдзрд┐ рдХрд╣реВрдВрдЧрд╛:
protected void onDraw(Canvas canvas) { if (measurementChanged) { measurementChanged = false; keyboard.initializeInstrument(getMeasuredHeight(), getContext()); instrumentWidth = keyboard.getWidth(); } keyboard.draw(canvas); }
рдореИрдВ рдЖрдкрдХреЛ рдорд╣рд╛рди рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдирд╣реАрдВ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдкрд┐рдпрд╛рдиреЛ рдХреЛ рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рдХреИрд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЙрдмрд╛рдК рдкрд╛рда рдФрд░ рдХреЛрдб рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕реНрдерд╛рди рд▓реЗрддрд╛ рд╣реИред рдЬреЛ рдХреЛрдИ рднреА рд╡рд┐рд╡рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ рд╡рд╣ рдореЗрд░рд╛ рдХреЛрдб рд▓реЗ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИред рдпрд╣рд╛рдВ рдореИрдВ рдХреЗрд╡рд▓ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░реВрдВрдЧрд╛ред
рдкрд╣рд▓рд╛ рдХрджрдо рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬреЗрд╢рди рд╣реИред рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдХреА рдЧрдгрдирд╛ рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИред
Key[] keysArray;
рдпрд╣ рд╣рдорд╛рд░рд╛ рдореЙрдбрд▓ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдПрдХ рдХреБрдВрдЬреА рд╣реИред рдХреБрдВрдЬреА рдЗрд╕рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ (рдШрдЯрдХ рд╕рдордиреНрд╡рдп рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ) рдФрд░ рдЖрдпрд╛рдореЛрдВ рдХреЛ рдЬрд╛рдирддреА рд╣реИ, рдЪрд╛рд╣реЗ рд╡рд╣ рдХрд╛рд▓рд╛ рдпрд╛ рд╕рдлреЗрдж рд╣реЛ, рдпрд╛ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рджрдмрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред
class Key { float startX; float endX; float startY; float endY; int midiCode; boolean black; boolean pressed = false; void setBounds(float startX, float endX, float startY, float endY) { this.startX = startX; this.startY = startY; this.endX = endX; this.endY = endY; } boolean containsPoint(float x, float y) { return startX <= x && endX > x && startY <= y && endY > y; } }
рдпрд╣ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдХреЗ рднреМрддрд┐рдХ рдЖрдХрд╛рд░ рдореЗрдВ рд╣рд░ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд╕рд╛рде рд╣реЛрддреА рд╣реИ, рд╣рдорд╛рд░рд╛ рдХреАрдмреЛрд░реНрдб рдЖрд░рдВрднреАрдХреГрдд рд╣реЛрддрд╛ рд╣реИ (рдЗрд╕рдХреЗ рд▓рд┐рдП рдорд╛рдкрдХ рдзреНрд╡рдЬ рдзреНрд╡рдЬ рдЙрддреНрддрд░рджрд╛рдпреА рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рдСрди-рдСрди рд╡рд┐рдзрд┐ рдореЗрдВ рд╕рддреНрдп рдкрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ)ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рд╣рд░ рдмрд╛рд░ рдЖрдХрд░реНрд╖рд┐рдд рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рдореБрдЦ рдкрджреЛрдВ рдХреА рдЧрдгрдирд╛ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред
рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдХреЛрдб public void initializeInstrument(float measuredHeight, Context context) { whiteKeyWidth = Math.round(measuredHeight / WHITE_KEY_ASPECT_RATIO); octaveWidth = whiteKeyWidth * 7; int blackHalfWidth = octaveWidth / 20; blackKeyHeight = Math.round(measuredHeight / BLACK_KEY_HEIGHT_PERCENT); keysArray = new Key[KEYS_IN_OCTAVE * OCTAVES]; int whiteIndex = 0; int blackIndex = 0; for (int i = 0; i < KEYS_IN_OCTAVE; i++) { Key key = new Key(); if (isWhite(i)) { key.black = false; key.setBounds(whiteKeyWidth * whiteIndex, whiteKeyWidth * whiteIndex + whiteKeyWidth, 0, measuredHeight); whiteIndex++; } else { key.black = true; int indexDisplacement = i == 1 || i == 3 ? 1 : 2; key.setBounds(whiteKeyWidth * (blackIndex + indexDisplacement) - blackHalfWidth, whiteKeyWidth * (blackIndex + indexDisplacement) + blackHalfWidth, 0, blackKeyHeight); blackIndex++; } key.midiCode = START_MIDI_CODE + i; keysArray[i] = key; } for (int i = KEYS_IN_OCTAVE; i < KEYS_IN_OCTAVE * OCTAVES; i++) { Key firstOctaveKey = keysArray[i % KEYS_IN_OCTAVE]; Key key = firstOctaveKey.clone(); key.startX += (i / KEYS_IN_OCTAVE) * octaveWidth; key.endX += (i / KEYS_IN_OCTAVE) * octaveWidth; key.midiCode = START_MIDI_CODE + i; keysArray[i] = key; } }
рдпрд╣рд╛рдВ рд╣рдо рдШрдЯрдХ рдХреА рдКрдВрдЪрд╛рдИ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреА рдЪреМрдбрд╝рд╛рдИ рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЪрд╛рдмрд┐рдпреЛрдВ рдХрд╛ рдПрдХ рд╕рд░рдгреА рдмрдирд╛рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдкрд╣рд▓реЗ рд╕рдкреНрддрдХ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд┐рд░ рдЗрд╕реЗ рдПрдХреНрд╕ рдЕрдХреНрд╖ рдХреЗ рд╕рд╛рде рдХреНрд▓реЛрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╢реЗрд╖ рдСрдХреНрдЯреЗрд╡реНрд╕ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рд╛рде рд╣реА, рдкреНрд░рддреНрдпреЗрдХ рдХреБрдВрдЬреА рдореЗрдВ рдПрдХ MIDI рдХреЛрдб рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдзреНрд╡рдирд┐ рдЪрд▓рд╛рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдорд┐рдбреА рдХреЛрдб рдореЗрдВ рдПрдВрдб-рдЯреВ-рдПрдВрдб рдирдВрдмрд░рд┐рдВрдЧ рд╣реИред рд╣рдорд╛рд░рд╛ рдкрд╣рд▓рд╛ рдореБрдЦреНрдп рдХреЛрдб START_MIDI_CODE рд╣реЛрдЧрд╛ред рдХрд┐рд╕реА рднреА рдХреБрдВрдЬреА рдХреЗ рдХреЛрдб рдХреА рдЧрдгрдирд╛ рдкреНрд░рд╛рд░рдВрдн рдХреЛрдб рдФрд░ рд╕рд░рдгреА рдореЗрдВ рдХреБрдВрдЬреА рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдЬреЛрдбрд╝рдХрд░ рдХреА рдЬрд╛рддреА рд╣реИред
рдЗрд╕рдХреЗ рдмрд╛рдж рдХреБрдВрдЬрд┐рдпреЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдкрд╛рджрди рд╣реИред рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рдкреВрд░реЗ рд╕рд░рдгреА рдкрд░ рдПрдХ рд▓реВрдк рдореЗрдВ, рд╣рдо рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
private void drawSingleKey(Canvas canvas, Key key, int firstVisibleKey, int lastVisibleKey) { Drawable drawable = key.black ? blackKeyDrawable : whiteKeyDrawable; drawable.setState(new int[] { key.pressed ? android.R.attr.state_pressed : -android.R.attr.state_pressed }); drawable.setBounds((int) key.startX, (int) key.startY, (int) key.endX, (int) key.endY); drawable.draw(canvas); }
рд░реЗрдВрдбрд░рд┐рдВрдЧ 2 рдЪрд░рдгреЛрдВ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкрд╣рд▓реЗ рд╣рдореЗрдВ рд╕рдлреЗрдж рдЪрд╛рдмрд┐рдпрд╛рдБ рдЦреАрдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдлрд┐рд░ рдХрд╛рд▓реЗ рд░рдВрдЧ рдХреА рддрд╛рдХрд┐ рдХреЛрдИ рдУрд╡рд░рд▓реЗ рди рд╣реЛред рд╣рдо рдЗрд╕рд╕реЗ рдмрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ 9-рдХреБрдВрдЬреА рдкреИрдЪ рдХреЛ рдЖрдпрддрд╛рдХрд╛рд░ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдХрдЯрдЖрдЙрдЯ рдХреЗ рд╕рд╛рдеред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рд╣рдореЗрдВ рдЕрддрд┐рд░рд┐рдХреНрдд рд░реАрдбреНрд░реЙрди рдкрд┐рдХреНрд╕рд▓ рдХреЛ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдкреНрд░рдпреЛрдЬрдиреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рд╣рдо рд╕рдмрдХреБрдЫ рд╕рдВрднрд╡ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрджрд┐рдо рд░рдЦреЗрдВред
рд╣реЛ рдЧрдпрд╛, рд╣рдорд╛рд░рд╛ рдЯреВрд▓ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рддреИрдпрд╛рд░ рд╣реЛ рдЧрдпрд╛ рд╣реИ:

рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИред рдмреЗрд╢рдХ, рдЬрдм рдЖрдк рдХреБрдВрдЬрд┐рдпреЛрдВ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЪрд▓реЛ рдЗрд╕реЗ рдареАрдХ рдХрд░рддреЗ рд╣реИрдВред
рдореБрдЦреНрдп рдмрд╛рддрдЪреАрдд
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреНрд▓рд┐рдХреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХреЗ рд▓рд┐рдП, рдСрди-рдЯрдЪ рд╡рд┐рдзрд┐ рдХреЛ рдЖрдорддреМрд░ рдкрд░ рдкреБрдирд░реНрдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛ рд╣реИ - рдПрдХ рдЙрдВрдЧрд▓реА рдХреЛ рд╕реНрдкрд░реНрд╢ рдХрд░реЗрдВ, рдПрдХ рдЗрд╢рд╛рд░рд╛ рдХрд░реЗрдВ, рджреЛрд╣рд░рд╛ рд╕реНрдкрд░реНрд╢ рдХрд░реЗрдВ, рд▓рдВрдмрд╛ рд╕реНрдкрд░реНрд╢ рдХрд░реЗрдВ, рдЖрджрд┐ рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдЬреНрдпрд╛рджрд╛рддрд░ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЖрдк рдФрд░ рдореИрдВ рдРрд╕реА рдкрд░реЗрд╢рд╛рдирд┐рдпреЛрдВ рд╕реЗ рдореБрдХреНрдд рд╣реИрдВред
рд╣рдо GestureDetector рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдХреГрдкрдпрд╛ рдЕрдкрдиреЗ рдкрд╣рд▓реЗ рджрд┐рдиреЛрдВ рд╕реЗ рдордВрдЪ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ред
рдЪрд▓рд┐рдП рд╣рдорд╛рд░реЗ рдЯреВрд▓ рдореЗрдВ
private GestureDetector gestureDetector;
рдлрд╝реАрд▓реНрдб
private GestureDetector gestureDetector;
рдФрд░ рдЗрд╕реЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВ
private void init() { if (!isInEditMode()) { gestureDetector = new GestureDetector(getContext(), gestureListener); } }
рд╣рдо рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛ рдХреЛ рд╢реНрд░реЛрддрд╛ рдЬреЗрд╕реНрдЪрд░рд▓рд┐рд╕реНрдЯ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рд╡рд╣ рд╕реНрдерд╛рди рд╣реИ рдЬрд╣рд╛рдВ рд╣рдо рдбрд┐рдЯреЗрдХреНрдЯрд░ рд╕реЗ рдХреЙрд▓рдмреИрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдХрд┐рд╕реА рднреА рдЗрд╢рд╛рд░реЛрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
private OnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() { public boolean onDown(MotionEvent e) { if (keyboard.touchItem(e.getX(), e.getY())) { invalidate(); } return true; } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { resetTouchFeedback(); return true; } public boolean onSingleTapUp(MotionEvent e) { resetTouchFeedback(); return super.onSingleTapUp(e); } };
рдЗрд╕рд▓рд┐рдП, рдСрдкрд░реЗрд╢рди рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рд╕рд░рд▓ рд╣реИ, рдСрдирдбрд╛рдЙрди рд╡рд┐рдзрд┐ рдореЗрдВ рд╣рдо рдЕрдкрдиреЗ рдХреАрдмреЛрд░реНрдб рдореЗрдВ рдХреАрд╕реНрдЯреНрд░реЛрдХ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рд╣рдо рджрдмрд╛рдП рдЧрдП рдХреБрдВрдЬреА рдХреЛ рдЦреЛрдЬрддреЗ рд╣реИрдВ (рдЯрдЪрдЖрдо рд╡рд┐рдзрд┐ рдХреБрдВрдЬреА рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рджреНрд╡рд╛рд░рд╛ рдЗрд╕рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ рдмрд┐рдирд╛ рдкреВрд░реЗ рд╕рд░рдгреА рдХреЛ рд╕реНрдХреИрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ)ред рдпрджрд┐ рдХреБрдВрдЬреА рдкрд╛рдИ рдЬрд╛рддреА рд╣реИ, рддреЛ рдЗрд╕реЗ рджрдмрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдЕрдорд╛рдиреНрдп рдХрд╣рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдХрд╛рд░рдг рд░рд┐рдбреНрд░рд╛рдЗрд╡рд┐рдВрдЧ рд╣реЛрддреА рд╣реИред
рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рдореЗрдВ, рд╣рдо рджрдмрд╛рдП рдЧрдП рдХреБрдВрдЬреА рдХреЛ рд░реАрд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ (рдЬрдм рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдирд╛, рдЙрдВрдЧрд▓реА рдХрд░рдирд╛, рдЖрджрд┐)ред рдпрд╣ рд╕рд╛рджреГрд╢реНрдп рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реВрдЪреА рджреГрд╢реНрдп рдХреЗ рд╕рд╛рде, рдЬрдм рд╣рдо рдПрдХ рд╢реАрдЯ рдХреЛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЪрдпрди рд░реАрд╕реЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рдЕрдЧрд▓рд╛ рдХрджрдо рдбрд┐рдЯреЗрдХреНрдЯрд░ рдХреЛ рд╣рдорд╛рд░реЗ рдШрдЯрдХ рд╕реЗ рдЬреЛрдбрд╝рдирд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рд╕рд░рд▓рддрд╛ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_CANCEL) { resetTouchFeedback(); } return super.onTouchEvent(event) || gestureDetector.onTouchEvent(event); }
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдо рдпрд╣ рднреА
ACTION_CANCEL
рдХрд┐ рдХреНрдпрд╛ рдХрд╛рд░реНрд░рд╡рд╛рдИ
ACTION_CANCEL
, рдФрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЪрдпрди рдХреЛ рднреА рд░реАрд╕реЗрдЯ рдХрд░реЗрдВ, рдХреНрдпреЛрдВрдХрд┐ GestureDetector рдХрд┐рд╕реА рднреА рддрд░рд╣ рд╕реЗ рдЗрд╕ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЕрдЧрд░ рдпрд╣ рдЕрдЪрд╛рдирдХ рд╣реБрдЖ, рддреЛ рд╣рдо рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рдЪрдпрдирд┐рдд рдХреБрдВрдЬреА рдХреЗ рд╕рд╛рде рд╢реЗрд╖ рд░рд╣рддреЗ рд╣реИрдВред
рд╣рдо рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ:

рд╣реБрд░реНрд░реЗ, рдЕрдм рдпрд╣ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬреАрд╡рд┐рдд рджрд┐рдЦрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рдЕрднреА рднреА рдХреАрдмреЛрд░реНрдб рдХрд╛ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рднрд╛рдЧ рджреЗрдЦрддреЗ рд╣реИрдВ ... рдпрд╣ рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВ рд╣реИ, рдЪрд▓реЛ рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рд╕реНрдХреНрд░реВ рдХрд░реЗрдВред
рдПрдХ рдШрдЯрдХ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рдЬреЛрдбрд╝рдирд╛
рддреЛ, рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдЗрдП рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рд╣рдо рдЕрдкрдиреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдХреИрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВрдЧреЗред рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдХреБрдЫ рднреА рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди, рдХреИрдирд╡рд╛рд╕ рдХреЛ рд╕реНрд╡рдпрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдХреИрдирд╡рд╕ рд╡рд░реНрдЧ рдЖрдкрдХреЛ рд╕реНрд╡рдпрдВ рдкрд░ affine рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЖрдЗрдП рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝реЗрдВ
private int xOffset;
рд╣рдорд╛рд░реА рдХрдХреНрд╖рд╛ рдХреЗ рд▓рд┐рдПред
рдЕрдм рд╣рдо рдЗрд╕ рддрд░рд╣ рд╕реЗ рдПрдХ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд╕рд╛рде рдЕрдкрдиреЗ onDraw рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░реЗрдВрдЧреЗ:
protected void onDraw(Canvas canvas) { if (measurementChanged) { measurementChanged = false; keyboard.initializeInstrument(getMeasuredHeight(), getContext()); instrumentWidth = keyboard.getWidth(); } canvas.save(); canvas.translate(-xOffset, 0); keyboard.updateBounds(xOffset, canvasWidth + xOffset); keyboard.draw(canvas); canvas.restore(); }
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдордиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛:
- рдХреИрдирд╡рд╕.рд╕реЗрд╡реЗ () - рдХреИрдирд╡рд╛рд╕ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЛ рдпрд╛рдж рдХрд░рддрд╛ рд╣реИред рдПрдХ рддрд░рд╣ рдХрд╛ рдмреНрд░реЗрдХрдкреЙрдЗрдВрдЯ рдмрдирд╛рддрд╛ рд╣реИ
- рдХреИрдирд╡рд╕.рдЯреНрд░рд╛рдВрд╕рд▓реЗрдЯ () - рдХреИрдирд╡рд╕ рдХреЛ рдПрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рджреВрд░реА рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ
- рдХреИрдирд╡рд╛рд╕ред рд╢реНрд░реЗрд╖реНрда () - рдХреИрдирд╡рд╛рд╕ рдХреЛ рдЙрд╕рдХреА рдореВрд▓ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВред
рд╣рдордиреЗ рдЕрдкрдиреЗ рдХреАрдмреЛрд░реНрдб рд╡рд░реНрдЧ рдореЗрдВ рдЕрдкрдбреЗрдЯрдмрд╛рдЙрдВрдб рд╡рд┐рдзрд┐ рдХреЛ рднреА рдЬреЛрдбрд╝рд╛ред рдпрд╣ рдЖрдкрдХреЛ рдмрд╛рдПрдВ рдФрд░ рджрд╛рдПрдВ рджреГрд╢реНрдпрдорд╛рди рд╕реАрдорд╛ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╣рдо рд╕реНрдХреНрд░реАрди рдХреЗ рдмрд╛рд╣рд░ рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдЪрд╛рдмрд┐рдпреЛрдВ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рди рдХрд░реЗрдВред рдРрд╕рд╛ рдЕрдиреБрдХреВрд▓рдиред
рдЕрдм рдЬрдм рд╣рдордиреЗ рдбреНрд░рд╛рдЗрдВрдЧ рдЪрд░рдг рдкрд░ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдореЗрдВ рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗ - GestureDetectorред OnScroll рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВ:
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { resetTouchFeedback(); xOffset += distanceX; if (xOffset < 0) { xOffset = 0; } if (xOffset > instrumentWidth - getMeasuredWidth()) { xOffset = instrumentWidth - getMeasuredWidth(); } invalidate(); return true; }
рд╣реЛ рдЧрдпрд╛, рдЕрдм рдЬрдм рд╣рдо рдЕрдкрдиреЗ рдХреАрдмреЛрд░реНрдб рдкрд░ рдЕрдкрдиреА рдЙрдВрдЧрд▓реА рдШреБрдорд╛рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдХреАрдмреЛрд░реНрдб рдХреЛ рдЫреЛрдбрд╝реЗ рдмрд┐рдирд╛ рдкреНрдпрд╛рд░рд╛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдЧрд╛ред рд▓реЗрдХрд┐рди рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред рд╣рдо рдЙрдВрдЧрд▓реА рдХреЛ рдЦреАрдВрдЪрдиреЗ рдФрд░ рдХреАрдмреЛрд░реНрдб рдХреА рдЬрдбрд╝рддрд╛ - рдлреНрд▓рд┐рдВрдЧ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рд╣рдореЗрдВ рдЙрдВрдЧрд▓реА рдХреА рдЧрддрд┐ рдФрд░ рд╕реНрдХреНрд░реАрди рдкрд░ рдЙрд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рддрдп рдХреА рдЧрдИ рджреВрд░реА рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдпрд╣ рд╕рдм рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкреНрд░рд┐рдп GestureDetector рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдореЗрдВ рд╕рд┐рд░реНрдл рдСрдирдлреНрд▓рд┐рдВрдЧ рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╡рд╣ рд╣рдореЗрдВ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдлрд╝реНрд▓рд┐рдВрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ, рд╕рд╛рде рд╣реА рд╕рд╛рде рдЙрд╕рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рднреАред рд▓реЗрдХрд┐рди рд╕реНрдХреНрд░реЙрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╢реБрд░реВ рдХрд░рдиреЗ рдФрд░ рдкрд╛рдареНрдпрдХреНрд░рдо рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдмреАрдЪ рдореЗрдВ рдЕрдВрддрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдФрд░ рдШрдЯрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рд╕реНрдХреЛрд░рд░, рдпрд╛ рдмрд▓реНрдХрд┐, рдЗрд╕рдХрд╛ рднрд╛рдИ - рдУрд╡рд░рд╕реНрдХреЙрд▓рд░ (рд╣рдо рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЪрдордХ рдкреНрд░рднрд╛рд╡ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ)ред Android рдореЗрдВ рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП Scroller рдПрдХ рдЕрддреНрдпрдВрдд рдЙрдкрдпреЛрдЧреА рдШрдЯрдХ рд╣реИ, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдирдЧрд┐рдирдд рдЖрдВрддрд░рд┐рдХ рдШрдЯрдХреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдорд╛рдирдХ рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред
рд╣рдорд╛рд░реЗ рдШреБрдордХреНрдХрдбрд╝ рдЬреЛрдбрд╝реЗрдВ:
private OverScroller scroller;
рдФрд░ рдШрдЯрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдореЗрдВ рдЗрд╕реЗ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВред
рдЗрд╕рдХреЗ рдмрд╛рдж, GestureDetector рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВ:
private OnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() { public boolean onDown(MotionEvent e) { scroller.forceFinished(true); if (keyboard.touchItem(e.getX() / scaleX + xOffset, e.getY())) { invalidate(); } return true; } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { scroller.fling(xOffset, 0, (int) -velocityX, 0, 0, instrumentWidth - getMeasuredWidth(), 0, 0); return true; }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдХреЛрдб рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдСрдлрд╕реЗрдЯ рдФрд░ рдЧрддрд┐ рдХреЗ рд╕рд╛рде рд╕реНрдХреЛрд░рд░ рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХреА рдиреНрдпреВрдирддрдо рдФрд░ рдЕрдзрд┐рдХрддрдо рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рдЕрдЧрд▓рд╛ рдХрджрдо рдСрдирдбреНрд░реЙ рд╣реИ
protected void onDraw(Canvas canvas) { if (scroller.computeScrollOffset()) { xOffset = scroller.getCurrX(); } if (measurementChanged) { measurementChanged = false; keyboard.initializeInstrument(getMeasuredHeight(), getContext()); instrumentWidth = keyboard.getWidth(); } canvas.save(); canvas.scale(scaleX, 1.0f); canvas.translate(xOffset , 0); keyboard.updateBounds(xOffset , canvasWidth + xOffset ); keyboard.draw(canvas); canvas.restore(); if (!scroller.isFinished()) { ViewCompat.postInvalidateOnAnimation(this); } }
рдпрд╣рд╛рдБ рдХреНрдпрд╛ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ? рдПрдиреАрдореЗрд╢рди рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдлреНрд░реЗрдо рдХреЗ рд▓рд┐рдП рдЬрд┐рд╕реЗ рд╣рдо scroller.computeScrollOffset () рдХрд╣рддреЗ рд╣реИрдВ, рдпрд╣ рд╡рд┐рдзрд┐ рд╕рд╣реА рд╣реИ рдпрджрд┐ рд╕реНрдХреЛрд░рд░ рдПрдирд┐рдореЗрдЯреЗрдб рд╣реИ, рддреЛ рд╣рдореЗрдВ xOffset рд╡реИрд░рд┐рдПрдмрд▓ рдХрд╛ рд╡рд░реНрддрдорд╛рди рдорд╛рди рдорд┐рд▓рддрд╛ рд╣реИред
рдЪреВрдБрдХрд┐ рдПрдиреАрдореЗрд╢рди рдореЗрдВ рд░рд┐рдбреНрд░реЗрд╕ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ - рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рдЕрдВрдд рдореЗрдВ рд╣рдо рдЬрд╛рдБрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╕реНрдХреЛрд░рд░ рдРрдирд┐рдореЗрдЯрд┐рдВрдЧ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдПрдиреАрдореЗрд╢рди рдХреЗ рдЕрдЧрд▓реЗ рдлреНрд░реЗрдо рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЬрдм рддрдХ рдХрд┐ рд╕реНрдХреЛрд░рд░ рдЕрдкрдирд╛ рдХрд╛рдо рдкреВрд░рд╛ рдирд╣реАрдВ рдХрд░рддрд╛, рдпрд╛ рдмрд▓ рджреНрд╡рд╛рд░рд╛ рд░реЛрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддрдм рддрдХ рдСрдирдбреНрд░рд╛рд╡ рд╡рд┐рдзрд┐ рдХреЛ рдЬрд┐рддрдиреА рдмрд╛рд░ рд╕рдВрднрд╡ рд╣реЛ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЕрдкрдиреЗ рдШрдЯрдХ рдХреЛ рдЖрдХрд░реНрд╖рд┐рдд рдХрд░реЗрдЧрд╛ред
рдЕрдм рд╣рдорд╛рд░рд╛ рдШрдЯрдХ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕реНрдХреНрд░реЙрд▓ рдХрд░реЗрдЧрд╛ рдФрд░ рдлреНрд▓рд┐рдВрдЧ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдЧрд╛ред рд▓реЗрдХрд┐рди рдХреБрдЫ рдпрд╛рдж рдЖ рд░рд╣рд╛ рд╣реИ, рд╣реИ рдирд╛? рдиреАрдЪреЗ рдкрд░реНрдпрд╛рдкреНрдд рдорд╛рдирдХ рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рдирд╣реАрдВ рд╣реИрдВред рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред
рдорд╛рдирдХ рдХреЙрд▓рдмрд╛рд░ рдЬреЛрдбрд╝рдирд╛
рдорд╛рдирдХ рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рдЬреЛрдбрд╝рдирд╛ рдПрдХ рдЬрд╛рджреВ рдХреА рддрд░рд╣ рд╣реИ, рдХреЛрдИ рд╡рд┐рд╢реЗрд╖ рд░рд╣рд╕реНрдп рдирд╣реАрдВ рд╣реИрдВ, рдмрд╕ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реИред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдЕрдкрдиреЗ рдШрдЯрдХ рдХреЛ рдмрддрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рднреА рдорд╛рдирдХ рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реА рдорд╛рди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ attrs.xml рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ, рдЬрд┐рд╕рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рднрд╛рд╖рд╛ рдЬреЛрдбрд╝реЗрдВ:
<declare-styleable name="View"> <attr name="android:fadeScrollbars" /> <attr name="android:scrollbarAlwaysDrawHorizontalTrack" /> <attr name="android:scrollbarAlwaysDrawVerticalTrack" /> <attr name="android:scrollbarDefaultDelayBeforeFade" /> <attr name="android:scrollbarFadeDuration" /> <attr name="android:scrollbarSize" /> <attr name="android:scrollbarStyle" /> <attr name="android:scrollbarThumbHorizontal" /> <attr name="android:scrollbarThumbVertical" /> <attr name="android:scrollbarTrackHorizontal" /> <attr name="android:scrollbarTrackVertical" /> <attr name="android:scrollbars" /> </declare-styleable>
рдЕрдм, рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ:
setVerticalScrollBarEnabled(false); setHorizontalScrollBarEnabled(true); TypedArray a = context.obtainStyledAttributes(R.styleable.View); initializeScrollbars(a); a.recycle();
рдЕрдЧрд▓рд╛ рдХрджрдо рддреАрди рд╕рд░рд▓ рддрд░реАрдХреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рдХреЗ рдЖрдХрд╛рд░ рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░реЗрдВрдЧреЗ:
protected int computeHorizontalScrollExtent() { return canvasWidth; } @Override protected int computeHorizontalScrollOffset() { return xOffset; } @Override protected int computeHorizontalScrollRange() { return instrumentWidth; }
рдХреЛрдб рдЦреБрдж рдХреЗ рд▓рд┐рдП рдмреЛрд▓рддрд╛ рд╣реИ - рдкрд╣рд▓реА рд╡рд┐рдзрд┐ рдореЗрдВ рд╣рдо рдЕрдкрдиреЗ рдШрдЯрдХ рдХреА рдЪреМрдбрд╝рд╛рдИ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВ, рджреВрд╕рд░реЗ рдореЗрдВ, рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ рдХреА рд╡рд░реНрддрдорд╛рди рдСрдлрд╕реЗрдЯ, рддреАрд╕рд░реЗ рдореЗрдВ рдкреВрд░реЗ рдХреАрдмреЛрд░реНрдб рдХрд╛ рдЖрдХрд╛рд░ (рдЬреЛ рд╕реНрдХреНрд░реАрди рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдкрд░реЗ рдЬрд╛рддрд╛ рд╣реИ)ред рдЕрдм рдпрд╣ рдЬрд░реВрд░рдд рдкрдбрд╝рдиреЗ рдкрд░ рдЗрди рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рдХреЛ "рд╡реЗрдХ рдЕрдк" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░рд╣рддрд╛ рд╣реИред рдмреЗрд╕ рд╡реНрдпреВ рдХреНрд▓рд╛рд╕ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ awakenScrollBars () рд╡рд┐рдзрд┐ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрдВрдХреНрддрд┐рдпрд╛рдБ рдЬреЛрдбрд╝реЗрдВ:
if (!awakenScrollBars()) { invalidate(); }
рд╣рдорд╛рд░реЗ GestureDetectorListener рдХреЗ onScroll рдФрд░ onFling рддрд░реАрдХреЛрдВ рдкрд░ред
рдкрд░рд┐рдгрд╛рдо - рдорд╛рдирдХ рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рд╣рдорд╛рд░реА рдЖрдБрдЦреЛрдВ рдХреЛ рдкреНрд░рд╕рдиреНрди рдХрд░рддреЗ рд╣реИрдВред

рдирд┐рд╖реНрдХрд░реНрд╖
рдЗрд╕рд▓рд┐рдП, рдЗрд╕ рднрд╛рдЧ рдореЗрдВ, рд╣рдордиреЗ рдПрдХ рдШрдЯрдХ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреА рдЬрд╛рдВрдЪ рдХреА, рдЬрд┐рд╕рдореЗрдВ рдбреНрд░реЙрдмрд▓реНрд╕, рд╡рд┐рднрд┐рдиреНрди рдбреНрд░реЙрдмрд▓реНрд╕ рд╕реНрдЯреЗрдЯреНрд╕, рд╡рд┐рдЬреБрдЕрд▓ рдлреАрдбрдмреИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдбреНрд░рд╛рдЗрдВрдЧ, рдЗрдВрдЯрд░реЗрдХреНрд╢рди рдХрд░рддреЗ рд╕рдордп, рд╕реНрдХреНрд░реЙрд▓рд┐рдВрдЧ, рдЬреЗрд╕реНрдЪрд░ рдХреЛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддреЗ рд╣реБрдП, рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рдмрдирд╛рддреЗ рд╣реБрдПред
рд▓реЗрдЦ рдХрд╛рдлреА рд▓рдВрдмрд╛ рдерд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реЗ рдХрдИ рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ рддреЛрдбрд╝рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред
рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ рдореИрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛:
- рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рддреЗ рд╕рдордп рдШрдЯрдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реЗрдЬрдирд╛
- рдУрд╡рд░рдХреНрд░реЛрд▓ рдХреЗ рд▓рд┐рдП рдмреИрдХрд▓рд╛рдЗрдЯ рдЬреЛрдбрд╝рдирд╛
- XML рдореЗрдВ рдкрд╛рд╕рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░
- рдЪреБрдЯрдХреА рдореЗрдВ рдЭреВрдордирд╛
рдореЗрд░реЗ рдкрд╛рд╕ рддреАрд╕рд░реЗ рднрд╛рдЧ рдХреА рдпреЛрдЬрдирд╛ рднреА рд╣реИ, рдЬрд╣рд╛рдВ рдореИрдВ рдЕрдиреБрдХреВрд▓рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛, рд░реЗрдбреАрдореЗрдб рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП рдмрд┐рдЯрдореИрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдФрд░ рдХреИрдирд╡рд╛рд╕ рдкрд░ рдбреНрд░рд╛рдЗрдВрдЧ (рдбреНрд░реЙрд░реНрдХрд▓, рдбреНрд░рд╛рдЯреИрдХреНрд╕, рдЖрджрд┐) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдореИрдВ рддреАрд╕рд░реЗ рд▓реЗрдЦ рдХреЛ рдХреЗрд╡рд▓ рддрднреА рд▓рд┐рдЦреВрдВрдЧрд╛ рдЬрдм рдкрд╣рд▓реЗ рджреЛ рдкрд╛рдардХреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдкреАрд▓ рдХрд░реЗрдВрдЧреЗ рдФрд░ рддреАрд╕рд░реЗ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдореЗрдВ рд░реБрдЪрд┐ рд╣реЛрдЧреА :)
рд▓реЗрдЦреЛрдВ рдХреА рдЗрд╕ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдореЗрд░реЗ github рдкрд░
goo.gl/VDeuw рдкрд░ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдореИрдВ рддреБрд░рдВрдд рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдпреЗ
рд╡рд┐рдХрд╕рд┐рдд рдХреА рдЬрд╛ рд░рд╣реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдХреНрд▓рд┐рдкрд┐рдВрдЧ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдЖрдкрдХреЛ рдХреБрдЫ рдХреЛрдб рдорд┐рд▓рддреЗ рд╣реИрдВ, рддреЛ рдРрд╕рд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдореИрдВ рд╕рдВрднрд╡рддрдГ рдЗрд╕реЗ рдиреЛрдЯрд┐рд╕ рдирд╣реАрдВ рдХрд░рддрд╛ рдФрд░ рдЗрд╕реЗ рдХрд╛рдЯ рджреЗрдирд╛ рднреВрд▓ рдЧрдпрд╛ред