Merhaba,bu uygulamayı kotlin ile Google'nin önerdiği son teknolojiler ile kodladım.
- Kullanıcılar dil öğrenmek için istediği sayıda kelime kaydedilebilir.
- Kelimelerin anımsanması için her kelime için bir resim çizilebilir.
- İnternetten aratılan kelimeye göre 3 milyon fotoğraf arasında seçim yapılabilir.
- Ana ekranda kaydedilen kelimeye tıklayarak kelimenin ayrıntıları görülebilmektedir.
Kullanıcılar bu sayfada önceden kaydettikleri kelimeleri recyclerview içinde görebilecektir.
private val swipeCallBack=object : ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT){
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val layoutPosition=viewHolder.layoutPosition
val selectedArt=wordRecyclerAdapter.words[layoutPosition]
viewModel.deleteArt(selectedArt)
}
}
}
Yukarıdaki kod sayesinde kullanıcı silmek istediği kelimeyi sağa veya sola sürükleyerek silebilecektir.
setOnClickListener {
onItemClickListener?.let {
it(nameToString,sentenceToString,urlToString)
}
}
Yukarıda recyclerviewde oluşturduğum fonksiyonu hilt sayesinde fragmentten direk çağırıp tıklanan elemanın bilgilerini details fragmente yollar.
fun setOnItemClickListener(listener : (String,String,String) -> Unit) {
onItemClickListener = listener
}
setOnClickListener {
onItemClickListener?.let {
it(nameToString,sentenceToString,urlToString)
}
}
wordRecyclerAdapter.setOnItemClickListener { word, sentence, url ->
viewModel.word=word
viewModel.sentence=sentence
viewModel.ımageUrl=url
findNavController().navigate(WordFragmentDirections.actionWordFragmentToDetailsFragment())
}
Yukarıdaki kod parçası recyclerviewden gelen bilgileri oluşturduğum viewmodeldeki değişkenlerin değerini belirlemek için kullanır.
Kullanıcı bu ekranda kaydedilen kelimenin ayrıntılarına ulaşabilir.
binding.detailsWord.text=viewModel.word
binding.detailsSentence.text=viewModel.sentence
glide.load(viewModel.ımageUrl).into(binding.detailsImageview)
Viewmodelden aldığımız güncel verileri kullanıcılar,glide sayesinde bu ekranda görebilir.
Kullanıcı bu ekranda kaydedilecek kelimeyi çizerek veya internetten stok görüntüyle mi kaydedeceğine karar verir.
binding.chooseImageview.setOnClickListener {
findNavController().navigate(ChoiceFragmentDirections.actionChoiceFragmentToApiFragment())
}
binding.drawingImageview.setOnClickListener {
findNavController().navigate(ChoiceFragmentDirections.actionChoiceFragmentToDrawingFragment())
}
Navigasyon kullanarak yukarıdaki kodlarla bu yönlendirmeyi kolaylıkla sağladım.
Kullanıcılar internetten resim seçmek istediklerinde bu ekran ile karşılaşacaklardır.Kelime ve cümle seçtikten sonra resim seçmek için imageviewe tıkladıktan sonra pixabay sitesine bir istek atılacaktır.Aşağıdaki kod parçası bunu göstermektedir.
interface RetrofitApi {
@GET("/api/")
suspend fun imageSearch(
@Query("q") searchQuery: String,
@Query("key") apiKey: String=API_KEY
): Response<Images>
}
Gelen yanıt room kullanılarak kaydedilecektir.
@Dao
interface WordDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertArt(art: Word)
@Delete
suspend fun deleteArt(art: Word)
@Query("SELECT * FROM words")
fun observeArt(): LiveData<List<Word>>
}
Dao bu şekilde kodlanmıştır.Hafıza yönetimi ve verimlilik için cevaplar liveData şeklinde alınmıştır.Gelen cevaplar üzerinde herhangi bir değişiklik veya filtreleme kullanmadığım için flow kullanma gereği duymadım ama flow ile de yapılabilir.
Resim seçmek için kelime girildikten sonra kullanıcı gridLayoutla yapılmış 16 elemanlı bir recyclerview ile karşılaşır.
var job: Job?=null
binding.searchText.addTextChangedListener {
job?.cancel()
job=lifecycleScope.launch {
delay(100)
it?.let {
if(it.toString().isNotEmpty()){
wordViewModel.searchForImage(it.toString())
}
}
}
}
}
Kullanıcının seçiminden sonra fragment destroy edildiğinde verimlilik için yazılan işin kapatılması gerekiyor bu nedenle yukarıdaki kodda görüldüğü üzere bir iş tanımladım.
Kullanıcı seçim ekranında çizerek kelime kaydetmeye karar verdiğinde yukarıdaki ekranda göründüğü üzere,resmi çizip sonrasında bunu kaydedebilir.
binding.save.setOnClickListener {
var bitmap = getBitmapFromView(binding.drawingLayout)
if (bitmap != null) {
smallBitmap=makeSmallBitmap(bitmap,200)
}
smallBitmap.saveImage(context = requireContext())
val imageUri = smallBitmap?.saveImage(requireContext()).toString()
println(imageUri)
wordViewModel.setSelectedImage(imageUri)
}
Kullanıcı kaydet butonuna tıklayınca önceden yazdığım makeSmallBitmap fonksiyonu sayesinde resim küçültülüp saveBitmap foksiyonu ile kaydedilir.
@Module
@InstallIn(SingletonComponent::class)
object Module {
@Singleton
@Provides
fun injectRoomDatabase(
@ApplicationContext context: Context
)= Room.databaseBuilder(
context,WordDatabase::class.java,"ArtBookDataBase"
).build()
@Singleton
@Provides
fun injectDao(dataBase: WordDatabase)=dataBase.wordDao()
Database için yazdığım hilt modul kodlarının bir kısmı yukarıda görülmektedir.
Uygulamayı yazan:Hozan BAYDU
Tasarım:Adobexd,Canva
Tarih:20.10.2022
iletişim:hozan.baydu3447@gmail.com