рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐
рд╕рд╛рдерд┐рдпреЛрдВ, рдлрд┐рд░ рд╕реЗ рдирдорд╕реНрдХрд╛рд░ред
рдЕрдкрдиреЗ
рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВрдиреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд░рд▓, рд▓реЗрдХрд┐рди рд╕реБрдВрджрд░ рдкрд┐рдпрд╛рдиреЛ рдХреАрдмреЛрд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдХрд╕реНрдЯрдо рдШрдЯрдХ рдмрдирд╛рдиреЗ рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдХреАрдВред

рдХрдЯ рдХреЗ рддрд╣рдд рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо
рд╕реАрдЯреА рдФрд░ ... рд╣рдорд╛рд░реЗ рдХреАрдмреЛрд░реНрдб рдХреА рдЕрддрд┐рд░рд┐рдХреНрдд рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдЬрд╛рд░реА рд░рдЦреЗрдВрдЧреЗред рдПрдЬреЗрдВрдбреЗ рдореЗрдВ:
- рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рддреЗ рд╕рдордп рдШрдЯрдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реЗрдЬрдирд╛
- рдУрд╡рд░рдХреНрд░реЛрд▓ рдХреЗ рд▓рд┐рдП рдмреИрдХрд▓рд╛рдЗрдЯ рдЬреЛрдбрд╝рдирд╛
- XML рдореЗрдВ рдкрд╛рд╕рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░
- рдорд▓реНрдЯреА-рдЯрдЪ рдЬреВрдо
рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рддреЗ рд╕рдордп рдШрдЯрдХ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд╣реЗрдЬрдирд╛
рдЕрдм рд╣рдо рдЕрдкрдиреЗ рдШрдЯрдХ рдореЗрдВ рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рд╣рдо рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рдПрдВ, рд╕реНрдХреНрд░реЙрд▓ рд╢реВрдиреНрдп рдкрд░ рд╣реЛрдЧрд╛ред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдЗрд╕рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рдЖрдк рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рддреЗ рд╣реИрдВ, рддреЛ рдЧрддрд┐рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╡реНрдпреВ рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдкрд╣рд▓реА рдмрд╛рдд рдЬреЛ рдпрд╣рд╛рдВ рдзреНрдпрд╛рди рдореЗрдВ рдЖрддреА рд╣реИ, рд╡рд╣ рд╣реИ рд╣рдорд╛рд░реА рдЧрддрд┐рд╡рд┐рдзрд┐ рдХрд╛
onSaveInstanceState()
рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛, рдШрдЯрдХ рд╕реЗ рд╕реНрдХреНрд░реЙрд▓ рдорд╛рди рдХреЛ рдЦреАрдВрдЪрдирд╛ рдФрд░ рд╕рд╣реЗрдЬрдирд╛, рдФрд░ рдмрд╛рдж рдореЗрдВ, рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рддреЗ рд╕рдордп рд╕реНрдХреНрд░реЙрд▓ рдХреЛ рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВред рдФрд░ рдпрд╣ рдХрд╛рдо рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рд╢рд╛рдпрдж рд╣реА рд╕рд╣реА рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕реЗ рд╕рд╣реЗрдЬрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рджрд╕, рдпрд╛ рдПрдХ рдШрдЯрдХ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рджрд╕ ... рджрд╕ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рдеред
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдПрдВрдбреНрд░реЙрдЗрдб рдХреЗ рдЖрдВрддрд░рд┐рдХ рддрдВрддреНрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рд╕рднреА рдШрдЯрдХреЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╕рдВрд░рдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдЖрдЦрд┐рд░рдХрд╛рд░, рдЖрдкрдХреЛ рд░реЛрдЯреЗрд╢рди рдХреЗ рджреМрд░рд╛рди ListView рдХрд╛ рд╕реНрдХреНрд░реЙрд▓ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд░рдирд╛ рд╣реИ, рд╣реИ рдирд╛? рдЗрд╕рд▓рд┐рдП рд╣рдо рдЙрд╕ рдЪреАрдЬрд╝ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдПрдВрдЧреЗ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рджреГрд╢реНрдп рдореЗрдВ рд╣реИ рдФрд░ рдЕрдВрджрд░ рд╕реЗ рдШрдЯрдХ рдХреА рд╕реНрдерд┐рддрд┐ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░реЗрдЧреА, рди рдХрд┐ рдмрд╛рд╣рд░ рд╕реЗред
рдФрд░ рдпрд╣ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд░реВрдк рд╕реЗ рд╕рд░рд▓ рд╣реИред рд╣рдореЗрдВ рд╡реНрдпреВ рдХреНрд▓рд╛рд╕
onSaveInstanceState()
рдФрд░
onRestoreInstanceState(Parcelable state)
рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЧрддрд┐рд╡рд┐рдзрд┐ рдореЗрдВ рдПрдирд╛рд▓реЙрдЧреНрд╕ рд╕реЗ рдереЛрдбрд╝рд╛ рдЕрдВрддрд░ рд╣реИред рд╡рд╣рд╛рдВ рд╣рдо
Bundle
рдХреЗ рд╕рд╛рде рд╕реМрджрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╛рд░реНрд╕рд▓рдмрд▓ рд╣реИред рд╣рдореЗрдВ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ Parcelable class рдмрдирд╛рдирд╛ рд╣реЛрдЧрд╛, рдЬреЛ
android.view.View.BaseSavedState
рдХрд╛ рд╡рдВрд╢рдЬ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
public static class SavedState extends BaseSavedState { int xOffset; int instrumentWidth;
рдпрд╣ рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред рдЕрдм рдпрд╣ рдХреЗрд╡рд▓ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИ:
@Override protected Parcelable onSaveInstanceState() { SavedState st = new SavedState(super.onSaveInstanceState()); st.xOffset = xOffset; st.instrumentWidth = xOffset; return st; } protected void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); xOffset = ss.xOffset; xOffset = ss.instrumentWidth; };
рд╣реЛ рдЧрдпрд╛ред рдпрджрд┐ рдЖрдк рдЕрдм рд╕реНрдХреНрд░реАрди рдХреЛ рдШреБрдорд╛рддреЗ рд╣реИрдВ, рддреЛ рд╕реНрдХреНрд░реЙрд▓ рдЦреЛ рдирд╣реАрдВ рдЬрд╛рдПрдЧрд╛ред рд▓реЗрдХрд┐рди рдПрдХ рдФрд░ рдЫреЛрдЯрд╛ рдХреЙрд╕реНрдореЗрдЯрд┐рдХ рд╡рд┐рд╡рд░рдг рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдЬреЛрдбрд╝реВрдВрдЧрд╛ред рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдореЗрдВ рдПрдХ рдШрдЯрдХ рдХреЛ рдореЛрдбрд╝рддреЗ рд╕рдордп, рдПрдХ рдЙрдЪреНрдЪ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдХреАрдмреЛрд░реНрдб рдХреА рдЪреМрдбрд╝рд╛рдИ рдмрджрд▓ рдЬрд╛рдПрдЧреА, рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реА рдКрдВрдЪрд╛рдИ рдмрджрд▓ рдЬрд╛рдПрдЧреА (рдкрд░рд┐рджреГрд╢реНрдп рдореЛрдб рдореЗрдВ рдХрдо), рдХреБрдВрдЬреА рд╕рдВрдХреАрд░реНрдг рдпрд╛ рд╡реНрдпрд╛рдкрдХ рд╣реЛ рдЬрд╛рдПрдЧреАред рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рд╕реНрдерд┐рд░ рдореВрд▓реНрдп xOffset, рдкреБрдирд░реНрдЧрдарди рдХреЗ рдмрд╛рдж рд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдХреЛ рд╕рдорд╛рдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдмрд╣реБрдд рд╕рд░рд▓рддрд╛ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЕрдкрдиреЗ рдХреАрдмреЛрд░реНрдб рдХреА рдкреБрд░рд╛рдиреА рдЪреМрдбрд╝рд╛рдИ рдХреЛ рдмрдирд╛рдП рд░рдЦреЗрдВрдЧреЗ рдЬрдм рд╣рдо рдЗрд╕реЗ рджреЛрдмрд╛рд░рд╛ рдмрдирд╛рдПрдВрдЧреЗред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рдореЗрдВ рдореИрдВ рд╣рдорд╛рд░реЗ рд╕реЗрд╡рдбрд╕реНрдЯреЗрдЯ рдореЗрдВ рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯ рдлреАрд▓реНрдб рдХреЛ рднреА рд╕реЗрд╡ рдХрд░рддрд╛ рд╣реВрдВред
рд╣рдорд╛рд░реЗ onDraw () рдореЗрдВ, рдЬрд╣рд╛рдВ рд╣рдо рдЗрд╕рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдШрдЯрдХ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд╢реЛрдзрдиреЛрдВ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:
if (measurementChanged) { measurementChanged = false; keyboard.initializeInstrument(getMeasuredHeight(), getContext()); float oldInstrumentWidth = instrumentWidth; instrumentWidth = keyboard.getWidth(); float ratio = (float) instrumentWidth / oldInstrumentWidth;
рдЕрдм, рдпрджрд┐ рдореЛрдбрд╝ рд╕реЗ рдкрд╣рд▓реЗ рд╣рдорд╛рд░рд╛ рд╕реНрдХреНрд░реЙрд▓ рдерд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рджреВрд╕рд░реЗ рд╕рдкреНрддрдХ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдпрд╣ рдореЛрдбрд╝ рдХреЗ рдмрд╛рдж рд╡рд╣реАрдВ рд░рд╣реЗрдЧрд╛ред
рдЗрд╕рд▓рд┐рдП, рд╣рдо рд░реЛрдЯреЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдЕрдкрдиреЗ рдШрдЯрдХ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВред рдЕрдм рд╣рдо рдЕрдзрд┐рдХ рджреГрд╢реНрдп рд╕реМрдВрджрд░реНрдп рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рддреН рд╕реНрдХреНрд░реЙрд▓ рдХреЗ рдЕрдВрдд рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдкрд░ рдкрдХреНрд╖реЛрдВ рдкрд░ рдЪрдордХ рдХрд╛ рдкреНрд░рднрд╛рд╡ред
рдУрд╡рд░рд╕реНрдХреНрд░реЙрд▓ рдХреЗ рд▓рд┐рдП рдЪрдордХ рдкреНрд░рднрд╛рд╡
рдЬреИрд╕рд╛ рдХрд┐ рдПрдХ рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рддреИрдпрд╛рд░-рдирд┐рд░реНрдорд┐рдд рдШрдЯрдХ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдЗрди рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рдЖрдХрд░реНрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдЗрд╕реЗ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдФрд░ рд╡реЙрдЗрд▓рд╛ рдореЗрдВ рдЫрдбрд╝реА рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рдШрдЯрдХ рдХреЛ
рдПрдЬрдлреЗрдХреНрдЯ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ рдЖрдИрд╕реАрдПрд╕ рдореЗрдВ рджрд┐рдЦрд╛рдИ рджрд┐рдпрд╛ред рд╣рдо
EdgeEffectCompat рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рд╕рдВрдЧрддрддрд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИ рдФрд░ EdgeEffect рдкрд░ рдПрдХ рдЖрд╡рд░рдг рд╣реИред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЙрди рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдореЗрдВ рдЬрд╣рд╛рдВ рдкреНрд░рднрд╛рд╡ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдпрд╣ рд╡рд░реНрдЧ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдареВрдВрда рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░реЗрдЧрд╛ рдФрд░ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рддреЛ, рд╣рдореЗрдВ рджреЛ рдкреНрд░рддрд┐рдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ - рдмрд╛рдПрдВ рдФрд░ рджрд╛рдПрдВ рдХрд┐рдирд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдПред
private EdgeEffectCompat leftEdgeEffect; private EdgeEffectCompat rightEdgeEffect;
рдЙрдиреНрд╣реЗрдВ рдЧрддрд┐рд╡рд┐рдзрд┐ рдореЗрдВ рдПрдХ рд╕рд░рд▓ рддрд░реАрдХреЗ рд╕реЗ рдЖрд░рдВрдн рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЕрдм, рдбреНрд░рд╛рдЗрдВрдЧред рд╕реНрдХреНрд░реЙрд▓рдмрд╛рд░ рдХреА рддрд░рд╣, рдкреНрд░рднрд╛рд╡ рд╕рднреА рд╕рд╛рдордЧреНрд░реА рдХреЗ рдКрдкрд░ рдЦреАрдВрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдЗрд╕реЗ рдбреНрд░рд╛ () рд╡рд┐рдзрд┐ рдореЗрдВ рд░рдЦрдирд╛ рдЙрдЪрд┐рдд рд╣реИред рдпрд╣рд╛рдВ рдореИрдВ рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЬреЛ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рд╡рд╣ рд╕рд╛рджреГрд╢реНрдп рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡реНрдпреВрдкреЗрдЬ рдХреНрд▓рд╛рд╕ рдореЗрдВ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╣рдо onDraw рдореЗрдВ рдкреНрд░рднрд╛рд╡ рдХреЛ рдмрд┐рд▓реНрдХреБрд▓ рдЙрд╕реА рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рде рдЖрдХрд░реНрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди, рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдпрд╣ рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдФрд░ рднреА рдЕрдзрд┐рдХ рд╕реБрдВрджрд░ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ onDraw рдореЗрдВ рд╣рдо рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдбреНрд░реЙ - рд╕рд┐рд╕реНрдЯрдо рдЗрдлреЗрдХреНрдЯ рдбрд╛рд▓рддреЗ рд╣реИрдВред
public void draw(Canvas canvas) { super.draw(canvas); boolean needsInvalidate = false; final int overScrollMode = ViewCompat.getOverScrollMode(this); if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS)) { if (!leftEdgeEffect.isFinished()) { final int restoreCount = canvas.save(); final int height = getHeight() - getPaddingTop() - getPaddingBottom(); final int width = getWidth(); canvas.rotate(270); canvas.translate(-height + getPaddingTop(), 0); leftEdgeEffect.setSize(height, width); needsInvalidate |= leftEdgeEffect.draw(canvas); canvas.restoreToCount(restoreCount); } if (!rightEdgeEffect.isFinished()) { final int restoreCount = canvas.save(); final int width = getWidth(); final int height = getHeight() - getPaddingTop() - getPaddingBottom(); canvas.rotate(90); canvas.translate(-getPaddingTop(), -width); rightEdgeEffect.setSize(height, width); needsInvalidate |= rightEdgeEffect.draw(canvas); canvas.restoreToCount(restoreCount); } } else { leftEdgeEffect.finish(); rightEdgeEffect.finish(); } if (needsInvalidate) { ViewCompat.postInvalidateOnAnimation(this); } }
рддреЛ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╛рдВрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╣рдорд╛рд░рд╛ рдШрдЯрдХ рдУрд╡рд░рдХреНрд░реЛрд▓ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рд╣рд╛рдВ, рддреЛ рджреЛрдиреЛрдВ рдкреНрд░рднрд╛рд╡реЛрдВ рдХреЛ рдЕрдиреБрдХреНрд░рдо рдореЗрдВ рдЦреАрдВрдЪ рд▓реЗрдВред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдПрдЬрдПрдлрд╝реЗрдХреНрдЯ рдЙрд╕ рджрд┐рд╢рд╛ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЗрд╕реЗ рдЦреАрдВрдЪрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдмрд╛рдИрдВ рдУрд░ рдпрд╛ рджрд╛рдИрдВ рдУрд░ рдкреНрд░рднрд╛рд╡ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЕрдкрдиреЗ рдХреИрдирд╡рд╛рд╕ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдШреБрдорд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
if (!leftEdgeEffect.isFinished()) { final int restoreCount = canvas.save(); final int height = getHeight() - getPaddingTop() - getPaddingBottom(); final int width = getWidth(); canvas.rotate(270); canvas.translate(-height + getPaddingTop(), 0); leftEdgeEffect.setSize(height, width); needsInvalidate |= leftEdgeEffect.draw(canvas); canvas.restoreToCount(restoreCount); }
рдпрд╣рд╛рдБ рд╣рдо рдХреНрд░рдо рдореЗрдВ рд╣реИрдВ:
- рдХреИрдирд╡рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреИрдирд╡рд╛рд╕ рдХреЛ рд╕рд╣реЗрдЬреЗрдВред рд╕реЗрд╡ ()
- рдЗрд╕рдХреА рдКрдВрдЪрд╛рдИ рдорд╛рдЗрдирд╕ рдкреИрдбрд┐рдВрдЧ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ рдФрд░ рдкреНрд░рднрд╛рд╡ рдЖрдХрд╛рд░ рдХреЛ рд▓реЗрдлреНрдЯ рдПрдЬрдлреИрдХреНрдЯ.рд╕реЗрдЯрд╕реЗрдЯ (рдКрдВрдЪрд╛рдИ, рдЪреМрдбрд╝рд╛рдИ) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реЗрдЯ рдХрд░реЗрдВ;
- рд╣рдо рдХреИрдирд╡рд╛рд╕ рдХреЛ 270 рдбрд┐рдЧреНрд░реА рддрдХ рдШреБрдорд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕реНрдерд┐рддрд┐ рджреЗрддреЗ рд╣реИрдВред
рдореИрдВ рдЗрд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЖрдЗрдП рдХреИрдирд╡рд╛рд╕ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рд╣рдЯрд╛ рджреЗрдВ:

рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░рднрд╛рд╡ рджрд┐рдЦрддрд╛ рд╣реИред рд╣рдореЗрд╢рд╛ рдиреАрдЪреЗред рдпрджрд┐ рд╣рдо рдХреЗрд╡рд▓ 270 рдХреЗ рд░реЛрдЯреЗрд╢рди рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдкреНрд░рднрд╛рд╡ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рдЦреАрдВрдЪрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреИрдирд╡рд╛рд╕ рдХреЗ рд╢реАрд░реНрд╖ рдХреЛрдиреЗ рдореЗрдВред

рдФрд░ рдХреЗрд╡рд▓ рдХреИрдирд╡рд╛рд╕ рдХреЗ рдСрдлрд╕реЗрдЯ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рднрд╛рд╡ рдЬрдЧрд╣ рдореЗрдВ рд╣реИред

рд▓реЗрдХрд┐рди рдореИрдВ рдЖрдЧреЗ рднрд╛рдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЬрдм рд╣рдо рдкрд░ рдкреНрд░рднрд╛рд╡ рдкрдбрд╝рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕реЗ рдЦреАрдВрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕реНрдХреНрд░реЙрд▓ рдХрд░рддреЗ рд╕рдордп рдпрд╣ рд╕рдХреНрд░рд┐рдп рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
рдпрд╣рд╛рдВ рд╣рдореЗрдВ рдЕрдкрдиреЗ рдЬреЗрд╕реНрдЪрд░ рдбрд┐рдЯреЗрдХреНрдЯрд░ рдкрд░ рд▓реМрдЯрдиреЗ рдФрд░ рдСрдирд╕реНрдХреНрд░рд╛реЕрд▓ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { resetTouchFeedback(); xOffset += distanceX; if (xOffset < 0) { leftEdgeEffect.onPull(distanceX / (float) getMeasuredWidth()); } if (xOffset > instrumentWidth - getMeasuredWidth()) { rightEdgeEffect.onPull(distanceX / (float) getMeasuredWidth()); } if (!awakenScrollBars()) { invalidate(); } return true; }
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдордиреЗ рд╕реАрдорд╛рдУрдВ рдХреЗ рд▓рд┐рдП xOffset рдХреЛ рд░реЛрдХрдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдХрд┐рдпрд╛ рдерд╛, рд╕рд╛рде рд╣реА, рд╣рдо рдЗрд╕реА рдкреНрд░рднрд╛рд╡ рдХреЗ рдСрдирдкреЙрд▓ рддрд░реАрдХреЗ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВред
рдпрд╣рд╛рдВ рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдЪреВрдВрдХрд┐ рд╣рдордиреЗ xOffset рд╡реИрд░рд┐рдПрдмрд▓ рдХреЛ рдпрд╣рд╛рдВ рд░реЛрдХрдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЗрд╕реЗ рдЕрдиреНрдп рдЬрдЧрд╣реЛрдВ рдкрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдпрд╣ рддреНрд░реБрдЯрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдСрдирдбреНрд░рд╛рдЗрд╡ рдФрд░ рдХрдВрдкреНрдпреВрдЯрд░реАрдпрд░ рдХреНрд╖реИрддрд┐рдЬ рдХреНрд░реЙрдирд┐рдХрд▓рдСрдлрд╕реЗрдЯ () рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рддрдХ рдореЗрд░реЗ рджрд┐рдорд╛рдЧ рд╕реЗ рдкрд╛рд░ рдирд╣реАрдВ рд╣реБрдЖ рд╣реИред
рдЕрдВрддрд┐рдо рд╕реНрдкрд░реНрд╢ рдЬрд┐рд╕реЗ рд╣рдо рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╡рд╣ рд╕реНрдХреНрд░реЙрд▓ рдЧрддрд┐ рдХрд╛ рдЕрд╡рд╢реЛрд╖рдг рд╣реИ рдЬрдм рдХрд┐рдирд╛рд░реЗ рд╣рдорд╛рд░реА рдЪрдордХ рддрдХ рдкрд╣реБрдВрдЪрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ
onDraw
рдореЗрдВ рдирд┐рдореНрди рдХреЛрдб рдЬреЛрдбрд╝реЗрдВ:
if (scroller.isOverScrolled()) { if (xOffset < 0) { leftEdgeEffect.onAbsorb(getCurrentVelocity()); } else { rightEdgeEffect.onAbsorb(getCurrentVelocity()); } }
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ,
Scroller.getCurrVelocity()
рд╡рд┐рдзрд┐ рдХреЗрд╡рд▓ рдЖрдИрд╕реАрдПрд╕ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрдкрд▓рдмреНрдз рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдПрдкреАрдЖрдИ 14+ рдХреЛ рд▓рдХреНрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рдзрд┐ рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ред рд╣рд╛рдВ, рдпрд╣ рдЖрджрд░реНрд╢ рд╕реЗ рдмрд╣реБрдд рджреВрд░ рд╣реИ, рд▓реЗрдХрд┐рди, рдлрд┐рд░ рд╕реЗ, рдпрд╣ рд╡рд╣реА рд╣реИ рдЬреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣реИред
рдЕрдм, рдЬрдм рд╣рдо рджреГрд╢реНрдп рдХреЗ рдмрд╛рд╣рд░ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рд╣реЛрд▓реЛ рдХреА рд╢реИрд▓реА рдореЗрдВ рдПрдХ рд╕реБрдВрджрд░ рдЪрдордХ рдорд┐рд▓рддреА рд╣реИред
XML рдореЗрдВ рдШрдЯрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝рдирд╛
рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд╕рд╛рде рд╕реАрдзреЗ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рд╕реА рд╕реБрд╡рд┐рдзрд╛ рдЬреЛрдбрд╝реВрдВрдЧрд╛ред рдЬрдм рдЖрдк рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдЗрд╕ рдиреЛрдЯ рдХреЗ рдирд╛рдо рдХреЗ рд╕рд╛рде рдПрдХ рд╡реГрддреНрдд рджреЗрдЦреЗрдВрдЧреЗред
рдпрд╣ рддреБрдЪреНрдЫ рддрд░реАрдХреЗ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВрдиреЗ рдиреЛрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рдПрдХ рд╕рд░рдгреА рд╢реБрд░реВ рдХреА
private ArrayList<Note> notesToDraw = new ArrayList<Note>();
рдФрд░ рдЬрдм рднреА рдореИрдВ рдХрд┐рд╕реА рдХреБрдВрдЬреА рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддрд╛ рд╣реВрдВ, рдореИрдВ рдХреБрдВрдЬреА рдХреЗ рдорд┐рдбреА рдХреЛрдб рджреНрд╡рд╛рд░рд╛ рдиреЛрдЯ рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ рдФрд░ рдЗрд╕реЗ рд╕рд░рдгреА рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВред рдпрд╣ рдХреИрд╕реЗ рд╣реЛрддрд╛ рд╣реИ рдЗрд╕рдХрд╛ рд╡рд┐рд╡рд░рдг рдЧреАрдереВрдм рдкрд░ рдХреЛрдб рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЕрдм рдХреАрдмреЛрд░реНрдб рд╡рд░реНрдЧ рдореЗрдВ рдореИрдВ drawOverlays (ArrayList) рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВ
public void drawOverlays(ArrayList<Note> notes, Canvas canvas) { int firstVisibleKey = getFirstVisibleKey(); int lastVisibleKey = getLastVisibleKey(); for (Note note : notes) { int midiCode = note.getMidiCode(); if (midiCode >= firstVisibleKey && midiCode <= lastVisibleKey) { drawNoteFromMidi(canvas, note, midiCode, false); } } } private void drawNoteFromMidi(Canvas canvas, Note note, int midiCode, boolean replica) { Key key = keysArray[midiCode - Keyboard.START_MIDI_CODE]; overlayTextPaint.setColor(circleColor); canvas.drawCircle(key.getOverlayPivotX(), key.getOverlayPivotY(), overlayCircleRadius, overlayTextPaint); String name = note.toString(); overlayTextPaint.getTextBounds(name, 0, name.length(), bounds); int width = bounds.right - bounds.left; int height = bounds.bottom - bounds.top; overlayTextPaint.setColor(Color.BLACK); canvas.drawText(name, key.getOverlayPivotX() - width / 2, key.getOverlayPivotY() + height / 2, overlayTextPaint); }
... рдФрд░ рдПрдХ рд╡реГрддреНрдд рдФрд░ рдкрд╛рда рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдиреЛрдЯ рдмрдирд╛рдПрдВред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рд╢рд╛рдпрдж рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рдЪреБрдХреЗ рд╣реИрдВ, рдореИрдВрдиреЗ рдРрд╕рд╛ рдХрд┐рдпрд╛ рд╣реИ рддрд╛рдХрд┐ рд╣рдо XML рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ рд╕рд░реНрдХрд▓ рдФрд░ рдкрд╛рда рдХреЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХреЗрдВред
рдЖрдЗрдП рд╣рдорд╛рд░реЗ рд╡реНрдпреВ рдХреА XML рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдореЗрдВ рд░рдВрдЧ, рд╕рд░реНрдХрд▓ рддреНрд░рд┐рдЬреНрдпрд╛ рдФрд░ рдкрд╛рда рдЖрдХрд╛рд░ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдбрд╛рд▓реЗрдВред рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдЙрдиреНрд╣реЗрдВ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, <рдШреЛрд╖рдгрд╛-рдпреЛрдЧреНрдп> рдЯреИрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
<declare-styleable name="PianoView"> <attr name="overlay_color" format="color"></attr> <attr name="overlay_circle_radius" format="dimension"></attr> <attr name="overlay_circle_text_size" format="dimension"></attr> </declare-styleable>
рдЗрд╕ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ attrs.xml рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред рдЕрдм, рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдЕрдкрдиреЗ рдШрдЯрдХ рдореЗрдВ рд▓реЛрдб рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ, рдирд┐рдореНрди рдХреЛрдб рдЬреЛрдбрд╝реЗрдВ
TypedArray pianoAttrs = context.obtainStyledAttributes(attrs, R.styleable.PianoView); int circleColor; float circleRadius; float circleTextSize; try { circleColor = pianoAttrs.getColor(R.styleable.PianoView_overlay_color, Color.GREEN); circleRadius = pianoAttrs.getDimension(R.styleable.PianoView_overlay_circle_radius, TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, context.getResources().getDisplayMetrics())); circleTextSize = pianoAttrs.getDimension(R.styleable.PianoView_overlay_circle_text_size, TypedValue .applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, context.getResources().getDisplayMetrics())); } finally { pianoAttrs.recycle(); }
рдЧреЗрдЯрдПрдХреНрд╕рдПрдХреНрд╕рдПрдХреНрд╕рдПрдХреНрд╕ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдореЗрдВ рдПрдХреНрд╕рдПрдХреНрд╕рдПрдХреНрд╕ рдХреА рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдореВрд▓реНрдп рдорд┐рд▓рддрд╛ рд╣реИред рдпрджрд┐ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЕрдиреБрдкрд▓рдмреНрдз рд╣реИ, рддреЛ рджреВрд╕рд░рд╛ рддрд░реНрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рдЕрдм рд╣рдорд╛рд░реЗ рдорд╛рд░реНрдХрдЕрдк рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╣реЗрдбрд░ рдореЗрдВ рдирд╛рдо рд╕реНрдерд╛рди рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
xmlns:piano="http://schemas.android.com/apk/res-auto"
, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рд╣рдореЗрдВ рдорд╛рд░реНрдХрдЕрдк рдХреЗ рд╕рд╛рде рдРрд╕реА рдлрд╛рдЗрд▓ рдорд┐рд▓рддреА рд╣реИ:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:piano="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".PianoDemoActivity" > <com.evilduck.piano.views.instrument.PianoView android:id="@+id/instrument_view" android:layout_width="match_parent" android:layout_height="300dip" piano:overlay_circle_radius="18dip" piano:overlay_circle_text_size="18sp" piano:overlay_color="#00FF00" /> </RelativeLayout>
рдЗрд╕ рддрд░рд╣, рд╣рдо рдЕрдкрдиреЗ рдШрдЯрдХреЛрдВ рдХреЛ рдорд╛рдирдХ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдШрдЯрдХреЛрдВ рдХреА рддрд░рд╣ рд▓рдЪреАрд▓рд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдорд▓реНрдЯреА-рдЯрдЪ рдЬреВрдо рд╕рдкреЛрд░реНрдЯ
рдЖрдЦрд┐рд░реА рдмрд╛рдд рдЬреЛ рдореИрдВ рдЖрдЬ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛, рд╡рд╣ рдорд▓реНрдЯреА-рдЯрдЪ рдЬреЗрд╕реНрдЪрд░ рдХреЗ рд╕рд╛рде рдмреЗрд╕рд┐рдХ рдЬреВрдо рд╕рдкреЛрд░реНрдЯ рд╣реИред
рдЬрд╝реВрдо рдЗрдлрд╝реЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
ScaleGestureDetector рдШрдЯрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рдХреЛрдб рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ GestureDetector рдХреЗ рд╕рдорд╛рди рд╣реИ, рдпрд╣ рдЕрд▓рдЧ рд╣реИ, рдХреЗрд╡рд▓ рд╢реНрд░реЛрддрд╛ рдЗрд╕реЗ рдкрд╛рд╕ рдХрд░рддрд╛ рд╣реИ:
private OnScaleGestureListener scaleGestureListener = new OnScaleGestureListener() { @Override public void onScaleEnd(ScaleGestureDetector detector) { } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public boolean onScale(ScaleGestureDetector detector) { scaleX *= detector.getScaleFactor(); if (scaleX < 1) { scaleX = 1; } if (scaleX > 2) { scaleX = 2; } ViewCompat.postInvalidateOnAnimation(PianoView.this); return true; } };
рд╣рдореЗрдВ рд╡реИрд░рд┐рдПрдмрд▓ рд╕реНрдХреЗрд▓ рдорд┐рд▓рд╛, рдЬреЛ рд╣рдорд╛рд░реЗ рдЬрд╝реВрдо рдХреЗ рд╕реНрддрд░ рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрд╕реЗ 1 рдФрд░ 2 рддрдХ рд╕реАрдорд┐рдд рдХрд░реЗрдЧрд╛ред
рдПрдХ рдФрд░ рд╕рд╡рд╛рд▓ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдЕрдкрдиреЗ рдХреАрдмреЛрд░реНрдб рдкрд░ рдЬрд╝реВрдо рдХреИрд╕реЗ рдХрд░реЗрдВрдЧреЗред рдЗрд╕ рд▓реЗрдЦ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╡рд┐рдХрд▓реНрдк рдЪреБрдирд╛ - рдмрд╕ рдХреИрдирд╡рд╛рд╕ рдХрдиреНрд╡рд░реНрдЯ рдХрд░реЗрдВред рд╣рд╛рдВ, рдпрд╣ рд╕рд╣реА рдирд╣реАрдВ рд╣реИ, рдФрд░ рдЗрд╕рд╕реЗ рддрд╕реНрд╡реАрд░ рд╡рд┐рдХреГрдд рд╣реЛ рдЬрд╛рдПрдЧреАред рд╕рд╣реА - рд╕реНрдХреЗрд▓рдПрдХреНрд╕ рдХреЗ рдореВрд▓реНрдп рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреА рдЪреМрдбрд╝рд╛рдИ рдмрдврд╝рд╛рдПрдВ, рд╣рд▓рдХреЛрдВ рдФрд░ рдкрд╛рда рдХреА рддреНрд░рд┐рдЬреНрдпрд╛ред рдпрд╣ рдореЗрд░реЗ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИ рдФрд░ рдЬреВрдо рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдмрд╕ рдХреИрдирд╡рд╛рд╕ рдХреЛ рд╕реНрдХреЗрд▓ рдХрд░рддреЗ рд╣реИрдВ:
canvas.save();
рд╣реЛ рдЧрдпрд╛, рдЕрдЧрд░ рдЖрдк рдЕрдкрдиреА рдЙрдВрдЧрд▓рд┐рдпреЛрдВ рд╕реЗ рдлреИрд▓рдиреЗ рд╡рд╛рд▓рд╛ рдЗрд╢рд╛рд░рд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдХреАрдмреЛрд░реНрдб рдЪреМрдбрд╝рд╛рдИ рдореЗрдВ рдХреИрд╕реЗ рдмрдврд╝рддрд╛ рд╣реИ:

рдирд┐рд╖реНрдХрд░реНрд╖
рдЗрд╕рд▓рд┐рдП рдореЗрд░реА рд▓реЗрдЦ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рджреВрд╕рд░рд╛ рднрд╛рдЧ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдпрд╛ рд╣реИред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рдХрд╕реНрдЯрдо рдШрдЯрдХреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреА рдЬрдЯрд┐рд▓рддрд╛рдУрдВ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдФрд░ рдЙрдирдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреА рдЧреБрдгрд╡рддреНрддрд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред
рдПрдХ рд╕рдорд╛рдкреНрдд рдЙрджрд╛рд╣рд░рдг рдЕрднреА рднреА рдореЗрд░реЗ github рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИ:
goo.gl/VDeuw ред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рджреГрдврд╝рддрд╛ рд╕реЗ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬ рд╕реЗ рдкрдврд╝реЗрдВ:
developer.android.com/training/gestures/index.htmlрддреАрд╕рд░реЗ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЕрдиреБрдХреВрд▓рди рдХреЗ рдореБрджреНрджреЛрдВ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛, рдкреНрд░реЛрдЧреНрд░рд╛рдореЗрдЯрд┐рдХ рд░реВрдк рд╕реЗ рдбреНрд░рд╛рдЗрдВрдЧ рдкрд╛рда рдХреЗ рдмрдЬрд╛рдп рдмрд┐рдЯрдореИрдк рдХрд╛ рдЙрдкрдпреЛрдЧ, рдордВрдбрд▓рд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдШрдЯрдХ рдореЗрдВ рдкрд┐рдХреНрд╕рд▓реНрд╕ рдХреА рдХреНрдпрд╛ рдХрдореА рд╣реЛрддреА рд╣реИ, рдФрд░ рдЙрдирд╕реЗ рдХреИрд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдпрд╛ рдЬрд╛рдПред