Advertisement
tuomasvaltanen

Untitled

May 4th, 2023 (edited)
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.25 KB | None | 0 0
  1. // Edistynyt mobiiliohjelmointi, 4.5.2023
  2.  
  3. // kolmannen osapuolen komponentit,
  4.  
  5. // SpinKit:
  6.  
  7. https://github.com/ybq/Android-SpinKit
  8.  
  9. Jos kokeillaan importata suoraan projektiin, tulee virhe, koska Android Studio ei löydä pluginia:
  10.  
  11. implementation 'com.github.ybq:Android-SpinKit:1.4.0'
  12.  
  13. // tämä korjaantuu sillä, että lisätään settings.gradle -tiedostoon molempiin repositoryihin jitpack-viittaus, eli:
  14.  
  15. maven { url "https://jitpack.io" }
  16.  
  17. eli koko tiedosto (paitsi pohjalla olevat projektin nimet ym.):
  18.  
  19. pluginManagement {
  20. repositories {
  21. google()
  22. mavenCentral()
  23. gradlePluginPortal()
  24. maven { url "https://jitpack.io" }
  25. }
  26. }
  27. dependencyResolutionManagement {
  28. repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  29. repositories {
  30. google()
  31. mavenCentral()
  32. maven { url "https://jitpack.io" }
  33. }
  34. }
  35.  
  36.  
  37. // kokeillaan esim. fragment_homen ulkoasussa:
  38.  
  39. <com.github.ybq.android.spinkit.SpinKitView
  40. android:id="@+id/spin_kit"
  41. style="@style/SpinKitView.Large.Circle"
  42. android:layout_width="wrap_content"
  43. android:layout_height="wrap_content"
  44. android:layout_gravity="center"
  45. app:SpinKit_Color="#E18835DC"
  46. app:layout_constraintBottom_toBottomOf="parent"
  47. app:layout_constraintEnd_toEndOf="parent"
  48. app:layout_constraintStart_toStartOf="parent"
  49. app:layout_constraintTop_toBottomOf="@+id/text_home" />
  50.  
  51.  
  52. // jos on tarve koodissa piilottaa latausanimaatio, voidaan tehdä esim. näin:
  53.  
  54. binding.spinKit.visibility = View.GONE
  55.  
  56. // tehdään seuraavaksi uusi fragment: CustomViewTesterFragment, lisätään päävalikkoon ja otetaan binding layer käyttöön
  57.  
  58. // esim.
  59. class CustomViewTesterFragment : Fragment() {
  60. private var _binding: FragmentCustomViewTesterBinding? = null
  61. // This property is only valid between onCreateView and
  62. // onDestroyView.
  63. private val binding get() = _binding!!
  64. override fun onCreateView(
  65. inflater: LayoutInflater,
  66. container: ViewGroup?,
  67. savedInstanceState: Bundle?
  68. ): View? {
  69. _binding = FragmentCustomViewTesterBinding.inflate(inflater, container, false)
  70. val root: View = binding.root
  71.  
  72.  
  73. return root
  74. }
  75. override fun onDestroyView() {
  76. super.onDestroyView()
  77. _binding = null
  78. }
  79. }
  80.  
  81.  
  82. // seuraavaksi testataan tätä pluginia (tässä uudessa fragmentissa):
  83.  
  84. https://github.com/anastr/SpeedView
  85.  
  86. // muokataan CustomViewTesterFragmentin ulkoasuksi LinearLayout helpomman testaamisen vuoksi:
  87.  
  88. <?xml version="1.0" encoding="utf-8"?>
  89. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  90. xmlns:tools="http://schemas.android.com/tools"
  91. android:layout_width="match_parent"
  92. android:layout_height="match_parent"
  93. android:orientation="vertical"
  94. tools:context=".CustomViewTesterFragment">
  95.  
  96.  
  97. </LinearLayout>
  98.  
  99. // lisätään SpeedViewin import kuntoon gradlessa:
  100.  
  101. implementation 'com.github.anastr:speedviewlib:1.6.0'
  102.  
  103. // kokeillaan nyt lisätä SpeedView ulkoasuun LinearLayoutin sisälle:
  104.  
  105. <com.github.anastr.speedviewlib.SpeedView
  106. android:id="@+id/speedView"
  107. android:layout_width="wrap_content"
  108. android:layout_height="wrap_content"
  109. android:layout_margin="20dp" />
  110.  
  111. // kokeillaan vaihtaa nopeus koodissa:
  112.  
  113. // kokeillaan nostaa npoeus 35:een
  114. binding.speedView.speedTo(35f)
  115.  
  116. // otetaan tremble-ominaisuus pois, ja muokataan LinearLayoutin XML:ää siten, että sieltä löytyy myös app-määritelmä:
  117.  
  118. // tämän avulla voimme muokata SpeedViewin ominaisuuksia suoraan XML:n kautta:
  119.  
  120. <?xml version="1.0" encoding="utf-8"?>
  121. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  122. xmlns:tools="http://schemas.android.com/tools"
  123. android:layout_width="match_parent"
  124. android:layout_height="match_parent"
  125. xmlns:app="http://schemas.android.com/apk/res-auto"
  126. android:orientation="vertical"
  127. tools:context=".CustomViewTesterFragment">
  128.  
  129. <com.github.anastr.speedviewlib.SpeedView
  130. android:id="@+id/speedView"
  131. app:sv_withTremble="false"
  132. android:layout_width="wrap_content"
  133. android:layout_height="wrap_content"
  134. android:layout_margin="20dp" />
  135.  
  136. </LinearLayout>
  137.  
  138. // muokataan lisää ominaisuuksia, vaihdetaan yksikkö Celsiukseen, ja alaraja -50 ja yläraja +50
  139.  
  140. <com.github.anastr.speedviewlib.SpeedView
  141. android:id="@+id/speedView"
  142. app:sv_withTremble="false"
  143. app:sv_minSpeed="-50"
  144. app:sv_maxSpeed="50"
  145. app:sv_unit="℃"
  146. android:layout_width="wrap_content"
  147. android:layout_height="wrap_content"
  148. android:layout_margin="20dp" />
  149.  
  150.  
  151. // kokeillaan esim. säädatalla (MQTT aiemmin)
  152.  
  153. <com.github.anastr.speedviewlib.SpeedView
  154. android:id="@+id/speedView_temperature"
  155. app:sv_withTremble="false"
  156. app:sv_minSpeed="-50"
  157. app:sv_maxSpeed="50"
  158. app:sv_unit="℃"
  159. android:layout_width="wrap_content"
  160. android:layout_height="wrap_content"
  161. android:layout_margin="20dp" />
  162.  
  163. // ja kytketään data binding layerin kautta,
  164.  
  165. activity?.runOnUiThread {
  166. binding.textViewWeatherText.text = text
  167. binding.speedViewTemperature.speedTo(temperature.toFloat())
  168. }
  169.  
  170. // kokeillaan vielä kalenteria hieman:
  171. https://github.com/npanigrahy/Custom-Calendar-View
  172.  
  173. // tehdään uusi fragment, esim. CalendarFragment, ja lisätään päävalikkoon
  174.  
  175. // uusi import gradleen:
  176.  
  177. implementation 'com.github.npanigrahy:Custom-Calendar-View:v1.1'
  178.  
  179. // ulkoasuun:
  180.  
  181.  
  182. <com.stacktips.view.CustomCalendarView
  183. android:id="@+id/calendar_view"
  184. android:layout_width="match_parent"
  185. android:layout_height="wrap_content"
  186. android:background="#ffffff">
  187. </com.stacktips.view.CustomCalendarView>
  188.  
  189. // muunnettuna Java-koodi Kotliniksi:
  190.  
  191. //Initialize calendar with date
  192. val currentCalendar: Calendar = Calendar.getInstance(Locale.getDefault())
  193.  
  194. //Show Monday as first date of week
  195. binding.calendarView.setFirstDayOfWeek(Calendar.MONDAY)
  196.  
  197. //Show/hide overflow days of a month
  198. binding.calendarView.setShowOverflowDate(false)
  199.  
  200. //call refreshCalendar to update calendar the view
  201. binding.calendarView.refreshCalendar(currentCalendar)
  202.  
  203. //Handling custom calendar events
  204. binding.calendarView.setCalendarListener(object : CalendarListener {
  205. override fun onDateSelected(date: Date?) {
  206. val df = SimpleDateFormat("dd-MM-yyyy")
  207. Toast.makeText(activity, df.format(date), Toast.LENGTH_SHORT).show()
  208. }
  209.  
  210. override fun onMonthChanged(date: Date?) {
  211. val df = SimpleDateFormat("MM-yyyy")
  212. Toast.makeText(activity, df.format(date), Toast.LENGTH_SHORT).show()
  213. }
  214. })
  215.  
  216.  
  217. // Omien custom viewien tekeminen, versio 1, Täysin oma custom view alusta asti
  218.  
  219. Tehdään uusi luokka projektiin (Kotlin class) => CustomTemperatureView
  220.  
  221. , Muokataan sisälle perusrunko CustomViewistä ilman ylimääräisiä funktioita:
  222.  
  223. class CustomTemperatureView @JvmOverloads constructor(
  224. context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
  225. ) : View(context, attrs, defStyleAttr) {
  226.  
  227. // your helper variables etc. can be here
  228. init
  229. {
  230. // this is constructor of your component
  231. // all initializations go here
  232. }
  233.  
  234. override fun onDraw(canvas: Canvas) {
  235. super.onDraw(canvas)
  236. // here you can do all the drawing
  237. }
  238.  
  239. override fun onMeasure(widthMeasureSpec : Int, heightMeasureSpec : Int){
  240. super.onMeasure(widthMeasureSpec, heightMeasureSpec)
  241. // Android uses this to determine the exact size of your component on screen
  242. }
  243. }
  244.  
  245. // kokeillaan asettaa värejä ja myös ympyrää ja tekstiä:
  246.  
  247. class CustomTemperatureView @JvmOverloads constructor(
  248. context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
  249. ) : View(context, attrs, defStyleAttr) {
  250. // your helper variables etc. can be here
  251. private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
  252. private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG)
  253.  
  254. init
  255. {
  256. // this is constructor of your component, all initializations go here
  257. // define the colors!
  258. paint.color = Color.BLUE
  259. textPaint.color = Color.BLACK
  260. }
  261.  
  262. override fun onDraw(canvas: Canvas) {
  263. super.onDraw(canvas)
  264. // here you can do all the drawing
  265. // you can do all the drawing through the canvas-object
  266. // parameters: x-coordinate, y-coordinate, size, color
  267. canvas.drawCircle(0f, 0f, 100f, paint)
  268.  
  269. // parameters: content, x, y, color
  270. canvas.drawText("Test!", 10f, 10f, textPaint);
  271. }
  272.  
  273. override fun onMeasure(widthMeasureSpec : Int, heightMeasureSpec : Int){
  274. super.onMeasure(widthMeasureSpec, heightMeasureSpec)
  275. // Android uses this to determine the exact size of your component on screen
  276. }
  277. }
  278.  
  279. // kokeillaan lisätä tämä CustomView tässä vaiheessa ulkoasuun, esim. CustomViewTesterFragment:
  280.  
  281. <com.example.edistynytandroid2023verkko.CustomTemperatureView
  282. android:layout_width="match_parent"
  283. android:layout_height="600dp"
  284. android:layout_margin="20dp" />
  285.  
  286.  
  287. Huom, paketin nimi on projektissasi eri kuin ohjaajalla
  288.  
  289. Ympyrä on näytöllä vielä melko sekavan näköinen, joten lisää tarvitsee koodia vielä.
  290.  
  291. Ihannetilanteessa Custom View pystyy itse päättelemään oikeat mittasuhteet, koordinaatit ja koot suoraan XML:ssä annetun tiedon perusteella. Esim. width ja height jos olisivat 200dp:
  292.  
  293. <com.example.edistynytandroid2023verkko.CustomTemperatureView
  294. android:layout_width="200dp"
  295. android:layout_height="200dp"
  296. android:layout_margin="20dp" />
  297.  
  298. Oletuksena Custom View ei tiedä näistä kokotiedoista mitään, vaan piirtää aina tasan sen mitä sinne on koodattu. Jotta XML:ssä olevat koot saadaan CustomViewin käyttöön, pitää meidän tehdä onMeasure sillä tavalla, että Android mittaa tietojen perusteella CustomViewin oikean koon näytöllä:
  299.  
  300. // tämän CustomViewin oletuskoko, 200 x 200
  301. val size = 200
  302.  
  303. override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
  304. // Try for a width based on our minimum
  305. val minw: Int = paddingLeft + paddingRight + suggestedMinimumWidth
  306. var w: Int = View.resolveSizeAndState(minw, widthMeasureSpec, 1)
  307.  
  308. // if no exact size given (either dp or match_parent)
  309. // use this one instead as default (wrap_content)
  310. if (w == 0)
  311. {
  312. w = size * 2
  313. }
  314.  
  315. // Whatever the width ends up being, ask for a height that would let the view
  316. // get as big as it can
  317. // val minh: Int = View.MeasureSpec.getSize(w) + paddingBottom + paddingTop
  318. // in this case, we use the height the same as our width, since it's a circle
  319. val h: Int = View.resolveSizeAndState(
  320. View.MeasureSpec.getSize(w),
  321. heightMeasureSpec,
  322. 0
  323. )
  324.  
  325. setMeasuredDimension(w, h)
  326. }
  327.  
  328. // tämän jälkeen voimme hyödyntää width-muuttujaa onDrawissa. ilman onMeasurea width-muuttuja on aina 0, minkä takia tämä ei suoraan toimi.
  329.  
  330. init
  331. {
  332. // this is constructor of your component, all initializations go here
  333. // define the colors!
  334. paint.color = Color.BLUE
  335. textPaint.color = Color.WHITE
  336. textPaint.textSize = 70f
  337. textPaint.textAlign = Paint.Align.CENTER
  338. }
  339.  
  340. override fun onDraw(canvas: Canvas) {
  341. super.onDraw(canvas)
  342. // here you can do all the drawing
  343. // you can do all the drawing through the canvas-object
  344. // parameters: x-coordinate, y-coordinate, size, color
  345. canvas.drawCircle(width.toFloat() / 2, width.toFloat() / 2, width.toFloat() / 2, paint)
  346.  
  347. // parameters: content, x, y, color
  348. // pieni 30px offset lisätty y-akseliin, jotta teksti on keskempänä näyttöä
  349. canvas.drawText("Test!", width.toFloat() / 2, width.toFloat() / 2 + 30, textPaint);
  350. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement