There are many errors about Recycler layout. In particular, I think nullpointrexception is the biggest error. After looking through several documents, I changed onCreate in Fragment Activity to onViewCreated and nullpointrexception was solved.
However, another error occurred, and the error was late init property instance has been initialized.
this is Error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.notei, PID: 21857
kotlin.UninitializedPropertyAccessException: lateinit property instance has not been initialized
at com.example.myrecyclerview.App$Companion.getInstance(App.kt:7)
at com.example.myrecyclerview.MyViewHolder.bind(MyViewHolder.kt:40)
at com.example.myrecyclerview.MyRecyclerAdapter.onBindViewHolder(MyRecyclerAdapter.kt:39)
at com.example.myrecyclerview.MyRecyclerAdapter.onBindViewHolder(MyRecyclerAdapter.kt:11)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7254)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
at android.view.View.layout(View.java:20672)
at android.view.ViewGroup.layout(ViewGroup.java:6194)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2792)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2319)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
at android.view.Choreographer.doCallbacks(Choreographer.java:761)
at android.view.Choreographer.doFrame(Choreographer.java:696)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
and This is App.kt
package com.example.myrecyclerview
import android.app.Application
class App: Application() {
companion object {
lateinit var instance: App
private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
and This is MyViewHolder.kt
package com.example.myrecyclerview
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.notei.R
import kotlinx.android.synthetic.main.layout_recycler_item.view.*
// 커스텀 뷰홀더
class MyViewHolder(itemView: View,
recyclerviewInterface: MyRecyclerviewInterface):
RecyclerView.ViewHolder(itemView),
View.OnClickListener{
val TAG: String = "로그"
private val usernameTextView = itemView.user_name_txt
private val profileImageView = itemView.profile_img
private var myRecyclerviewInterface: MyRecyclerviewInterface? = null
//기본 생성자
init {
Log.d(TAG, "MyViewHolder - init() called")
itemView.setOnClickListener(this)
this.myRecyclerviewInterface = recyclerviewInterface
}
//데이터와 뷰를 묶는다.
fun bind(myModel: MyModel) {
Log.d(TAG, "MyViewHolder - bind() called")
// 텍스트뷰와 실제 텍스트 데이터를 묶는다.
usernameTextView.text = myModel.name
// 이미지뷰와 실제 이미지 데이터를 묶는다.
Glide
.with(App.instance)
.load(myModel.profileImage)
// .centerCrop()
.placeholder(R.mipmap.ic_launcher) //값이 없을 때
.into(profileImageView)
}
override fun onClick(v: View?) {
Log.d(TAG, "MyViewHolder - onClick() called")
this.myRecyclerviewInterface?.onItemClicked(adapterPosition)
}
}
and This is MyRecyclerAdapter.kt
package com.example.myrecyclerview
import android.content.ContentValues.TAG
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.example.notei.R
class MyRecyclerAdapter(myRecyclerviewInterface: MyRecyclerviewInterface): RecyclerView.Adapter<MyViewHolder>() {
val TAG: String = "로그"
private var modelList = ArrayList<MyModel>()
private var myRecyclerviewInterface: MyRecyclerviewInterface? = null
// 생성자
init {
this.myRecyclerviewInterface = myRecyclerviewInterface
}
// 뷰홀더가 생성 되었을때
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
// 연결할 레이아웃 설정
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_recycler_item, parent, false), this.myRecyclerviewInterface!!)
}
// 목록의 아이템 수
override fun getItemCount(): Int {
return this.modelList.size
}
// 뷰와 뷰홀더가 묶였을 때(재활용되었을 때)
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
Log.d(TAG, "MyRecyclerAdapter - onBindVIewHolder() called / position: $position")
holder.bind(this.modelList[position])
}
// 외부에서 데이터 넘기기
fun submitList(modelList: ArrayList<MyModel>) {
this.modelList = modelList
}
}
and This is Fragment_1.kt
package com.example.notei
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myrecyclerview.MyModel
import com.example.myrecyclerview.MyRecyclerAdapter
import com.example.myrecyclerview.MyRecyclerviewInterface
import kotlinx.android.synthetic.main.activity_home.*
import kotlinx.android.synthetic.main.fragment_1.*
class Fragment_1: Fragment(R.layout.fragment_1), MyRecyclerviewInterface {
val TAG: String = "로그"
//데이터 담을 배열
var modelList = ArrayList<MyModel>()
private lateinit var myRecyclerAdapter: MyRecyclerAdapter
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//recyclerview adapter
Log.d(TAG, "MainActivity - onCreate() called")
Log.d(TAG, "MainActivity - 반복문 돌리기 전 this.modelList.size : ${this.modelList.size}")
// 10번 반복
for (i in 1..10) {
val myModel = MyModel(name = "장인수 $i", profileImage = "https://edcan.kr/static/media/EDCAN_LOGO.2b1b47ce.svg")
this.modelList.add(myModel)
}
Log.d(TAG, "MainActivity - 반복문 돌린 후 this.modelList.size : ${this.modelList.size}")
// 어답터 인스턴스 생성
myRecyclerAdapter = MyRecyclerAdapter(this)
myRecyclerAdapter.submitList(this.modelList)
// 리사이클러뷰 설정
my_recycler_view.apply {
// 리사이클러뷰 방향 등 설정
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
// 어답터 장착
adapter = myRecyclerAdapter
}
}
override fun onItemClicked(position: Int) {
Log.d(TAG, "MainActivity - onItemClicked() called / position $position")
var name: String? = null
// 값이 비어있으면 ""를 넣는다.
// unwrapping - 언랩핑
val title: String = this.modelList[position].name ?: ""
//
// val title: String = name ?: "ㅎㅎ"
AlertDialog.Builder(requireContext())
.setTitle(title)
.setMessage("$title 의 코딩:")
.setPositiveButton("오케이") {
dialog, id -> Log.d(TAG, "MainActivity - 다이얼로그 확인 버튼 클릭했음")
}
.show()
}
}
and This is fragment_1.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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=".HomeActivity"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:id="#+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
and This is layout_recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="20dp"
app:cardCornerRadius="20dp"
app:cardElevation="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="20dp">
<ImageView
android:id="#+id/profile_img"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="#mipmap/ic_launcher"
/>
<TextView
android:id="#+id/user_name_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="장인수"
android:textSize="30sp"
android:layout_marginStart="20dp"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</androidx.cardview.widget.CardView>
+)For those who need it.
app/build.gradle
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions' //add
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //android 4.1 down:D
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.notei"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
viewBinding {
enabled = true
}
}
dependencies {
// firebase add
implementation platform('com.google.firebase:firebase-bom:28.1.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-auth:21.0.1'
implementation 'com.google.firebase:firebase-firestore-ktx:23.0.1'
implementation 'com.google.firebase:firebase-storage-ktx'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha04' //viewpager2
implementation 'androidx.legacy:legacy-support-v4:1.0.0'//viewpager2
implementation 'androidx.recyclerview:recyclerview:1.1.0' //recyclerview
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation 'com.google.android.material:material:1.3.0-alpha03' //Material Design
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
// imageView url 사용하기
implementation 'com.squareup.picasso:picasso:2.71828'
// 리사이클러뷰
implementation "androidx.recyclerview:recyclerview:1.2.0" //recyclerView
implementation "androidx.recyclerview:recyclerview-selection:1.1.0"//recyclerView
// 카트뷰
implementation "androidx.cardview:cardview:1.0.0" //cardview
// 글라이드 - 이미지 처리
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
}
//add
// Task 'wrapper' not found in project ':app'. 라는 오류가 나와서 추가함 구글 검색해보니가 하라고 카더라
task wrapper(type: Wrapper) {
gradleVersion = '2.0'
}
I want recyclerLayout printed on fragment_1.xml
thank you so much
Related
I need help please, i'm getting errors in fragment.kt in process of getting a camera set up
**
//fragmentcamera.xml
**
**<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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=".MainActivity">
<androidx.camera.view.PreviewView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/preview"/>
<Button
android:id="#+id/btnTakePhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="Take photo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#id/btnDisplayGallery"
app:layout_constraintBottom_toBottomOf="parent"/>
<Button
android:id="#+id/btnDisplayGallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:layout_marginBottom="300dp"
android:text="Display gallery"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/btnTakePhoto" />
</androidx.constraintlayout.widget.ConstraintLayout>**
The following are images for camerafragment.kt
s
the errors that i am getting
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.fragment.app.Fragment
import com.google.common.util.concurrent.ListenableFuture
import java.io.File
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class cameraFragment : Fragment() {
// TODO: Rename and change types of parameters
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
//ListenableFuture interface listens for async operations external to
// main thread
// requires type of activity being observed - ProcessCameraProvider
private lateinit var cameraProviderFuture:
ListenableFuture<ProcessCameraProvider>
//used to decide whether to use front or back camera
private lateinit var cameraSelector: CameraSelector
//use case for capturing images
private var imageCapture: ImageCapture? = null
//interface that extends Executor to provide thread for capturing an image
private lateinit var imgCaptureExecutor: ExecutorService
//static variables
companion object {
//used for messages output in debugger
val TAG = "cameraFragment"
//used to check request code
private var REQUEST_CODE = 101
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for requireActivity() fragment
val view: View = inflater.inflate(
R.layout.xml_camera,
container,
false
)
//get instance of ProcessCameraProvider
cameraProviderFuture = ProcessCameraProvider.getInstance(requireActivity())
//set default to back camera
cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
//instantiate imgCaptureExecutor
imgCaptureExecutor = Executors.newSingleThreadExecutor()
//check for permissions (similar to other sensors)
if (ActivityCompat.checkSelfPermission(
requireActivity(),
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
)
//request permissions
ActivityCompat.requestPermissions(
requireActivity(),
arrayOf(
//array containing required permissions
Manifest.permission.CAMERA
),
REQUEST_CODE
)
else {
//if permission already granted, start camera
startCamera()
}
//set up event listener for btnCapture click
val btnTakePhoto: Button = view.findViewById(R.id.btnTakePhoto)
btnTakePhoto.setOnClickListener {
takePhoto()
} //set up event listener for btnGallery click
val btnDisplayGallery: Button = view.findViewById(R.id.btnDisplayGallery)
btnDisplayGallery.setOnClickListener {
displayGallery()
}
return view
}
//invoked when permissions change
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
//check that request code matches and permission granted
if (requestCode == REQUEST_CODE &&
grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
//if permission now granted, start camera
startCamera()
}
}
//listen for data from camera
private fun startCamera() {
cameraProviderFuture.addListener(
{
//create ProcessCameraProvider instance
val cameraProvider = cameraProviderFuture.get()
//connect preview use case to the preview in the xml file
val preview: PreviewView = requireView().findViewById(R.id.preview)
val previewCase = Preview.Builder().build().also {
it.setSurfaceProvider(preview.surfaceProvider)
}
//instantiate capture use case
imageCapture = ImageCapture.Builder().build()
try {
//clear all bindings to previous use cases first
cameraProvider.unbindAll()
//bind lifecycle of camera to lifecycle of application
cameraProvider.bindToLifecycle(
requireActivity(),
cameraSelector, previewCase
)
cameraProvider.bindToLifecycle(
requireActivity(), cameraSelector,
imageCapture
)
} catch (e: Exception) {
Log.d(TAG, "Use case binding failed")
}
},
//run asynchronous operation being listened to by cameraProviderFuture
ContextCompat.getMainExecutor(requireActivity())
)
}
//take photo
private fun takePhoto() {
imageCapture?.let {
//create file with fileName using timestamped in milliseconds
val file = File(
requireActivity().externalMediaDirs[0],
"snap_${System.currentTimeMillis()}"
)
//save image in above file
val outputFileOptions =
ImageCapture.OutputFileOptions.Builder(file).build()
//call takePicture method with where to find image
it.takePicture(
outputFileOptions,
imgCaptureExecutor,
//set up callbacks for when picture is taken
object : ImageCapture.OnImageSavedCallback {
override fun onImageSaved(
outputFileResults:
ImageCapture.OutputFileResults
) {
Log.i(TAG, "Image saved in ${file.toUri()}")
}
override fun onError(exception: ImageCaptureException) {
Toast.makeText(
requireActivity(),
"Error taking photo",
Toast.LENGTH_LONG
).show()
Log.i(TAG, "Error taking photo: $exception")
}
}
)
}
animateFlash()
}
//flash to provide feedback that photo taken
private fun animateFlash() {
val preview: PreviewView = requireView().findViewById(R.id.preview)
preview.postDelayed({
preview.foreground = ColorDrawable(Color.argb(125, 255, 255, 255))
preview.postDelayed({
preview.foreground = null
}, 30)
}, 60)
}
//display gallery
private fun displayGallery() {
val intent = Intent(requireActivity(), GalleryActivity::class.java)
startActivity(intent)
}
}
Replace all "this,getApplicationContext" with getActivity(). In Java
Replace all "this,getApplicationContext" with activity. In Kotlin.
Two likely definitions:
getActivity() in a Fragment returns the Activity the Fragment is currently associated with. (see http://developer.android.com/reference/android/app/Fragment.html#getActivity()).
getActivity() is user-defined.
i try to build a sample app using the navigation drawer activitiy and a listview in one of the sub fragments. Therefor i created the project and then added a list fragment to res.layout.navigation.mobile_navigation.
So far so nice. When compiling in ItemRecyclerViewAdapter the following error occurs:
import com.example.mydatabindingtest.databinding.FragmentItemBindingImpl;
^
symbol: class FragmentItemBindingImpl
location: package com.example.mydatabindingtest.databinding
After reading a lot i suppose this file should be generates automatically when creating the app. So the question is why is the file not created. Or if i'm wrong how should the file look like.
I'm using:
Android Studio 4.2
Gradle 4.2.0
Kotlin 1.5.0
All kept up to date by updating when prompted.
Here the code snippets i think you need to help:
build.gradle(:app)
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.mydatabindingtest"
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
dataBinding true
viewBinding true
}
}
fragment_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class="FragmentItemBinding">
<variable
name="item"
type="com.example.mydatabindingtest.ui.listview.placeholder.PlaceholderContent.PlaceholderItem" />
</data>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/item_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:text="#{item.id}"/>
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="#dimen/text_margin"
android:textAppearance="?attr/textAppearanceListItem"
android:text="#{item.content}"/>
</LinearLayout>
</layout>
MyItemRecyclerViewAdapter.kt
package com.example.mydatabindingtest.ui.listview
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.example.mydatabindingtest.R
import com.example.mydatabindingtest.ui.listview.placeholder.PlaceholderContent.PlaceholderItem
import com.example.mydatabindingtest.ui.listview.databinding.FragmentItemBinding
/**
* [RecyclerView.Adapter] that can display a [PlaceholderItem].
* TODO: Replace the implementation with code for your data type.
*/
class MyItemRecyclerViewAdapter(
private val values: List<PlaceholderItem>
) : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
FragmentItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = values[position]
holder.idView.text = item.id
holder.contentView.text = item.content
}
override fun getItemCount(): Int = values.size
inner class ViewHolder(binding: FragmentItemBinding) : RecyclerView.ViewHolder(binding.root) {
val idView: TextView = binding.itemNumber
val contentView: TextView = binding.content
override fun toString(): String {
return super.toString() + " '" + contentView.text + "'"
}
}
}
I appologize if the question is already answered. To defend my self, i did not find the answer after searching for several hours, since the answers i read are farly old and did not solve my problem.
So your help will be apreciated.
Best regards
EDIT:
After domicoders question, i rebuilt the hole project. Now the three following errors are shown:
e: G:\Projekte\Android\MyDataBindingTest\app\src\main\java\com\example\mydatabindingtest\ui\listview\MyItemRecyclerViewAdapter.kt: (11, 50): Unresolved reference: databinding
e: G:\Projekte\Android\MyDataBindingTest\app\src\main\java\com\example\mydatabindingtest\ui\listview\MyItemRecyclerViewAdapter.kt: (24, 13): Unresolved reference: FragmentItemBinding
e: G:\Projekte\Android\MyDataBindingTest\app\src\main\java\com\example\mydatabindingtest\ui\listview\MyItemRecyclerViewAdapter.kt: (41, 37): Unresolved reference: FragmentItemBinding
The reason for these messages is that the required class is not existing. But why does android studio insert the questionable import when the file is not created automatically. Or am i mistanken at some point?
Best regards
As stated here, enable databinding in your App Level build.gradle file
android {
...
dataBinding{
enabled=true
}
}
This is my first project using Kotlin, so I'm practice to create an app and using architecture components Room Database, Android View Model and LiveData, but I got this error message.
And the mobile crash unexpectedly,
I don't know how to solve it.
Thanks.
The build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "kotlin-kapt"
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.leaf76.architectureexample"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
def lifecycle_version = "2.2.0"
def room_version = "2.2.5"
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
// com.android.support.cardview => androidx
implementation "androidx.cardview:cardview:1.0.0"
// com.android.support.design => androidx
implementation "com.google.android.material:material:1.0.0"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// Annotation processor
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// Room
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
}
Error message
2020-03-27 02:50:27.987 12708-12708/com.leaf76.architectureexample E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.leaf76.architectureexample, PID: 12708
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.leaf76.architectureexample/com.leaf76.architectureexample.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.leaf76.architectureexample.NoteViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3448)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7811)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.leaf76.architectureexample.NoteViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.leaf76.architectureexample.MainActivity.onCreate(MainActivity.kt:21)
at android.app.Activity.performCreate(Activity.java:7955)
at android.app.Activity.performCreate(Activity.java:7944)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3423)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7811)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
Caused by: java.lang.InstantiationException: java.lang.Class<com.leaf76.architectureexample.NoteViewModel> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.leaf76.architectureexample.MainActivity.onCreate(MainActivity.kt:21)
at android.app.Activity.performCreate(Activity.java:7955)
at android.app.Activity.performCreate(Activity.java:7944)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3423)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7811)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
Note.kt
package com.leaf76.architectureexample
import androidx.room.Entity
import androidx.room.PrimaryKey
#Entity(tableName = "note_table")
data class Note(var title: String, var description: String, var priorty: Int) {
#PrimaryKey(autoGenerate = true)
var Id: Int = 0
}
NoteDatabase
package com.leaf76.architectureexample
import android.content.Context
import android.os.AsyncTask
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
#Database(entities = [Note::class], version = 1, exportSchema = false)
abstract class NoteDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDao
// static parameters
companion object {
private lateinit var instance: NoteDatabase
fun getInstance(context: Context): NoteDatabase {
if (instance == null) {
synchronized(NoteDatabase::class.java) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java, "note_database"
)
.fallbackToDestructiveMigration()
.addCallback(roomCallbackL)
.build()
}
}
return instance
}
private val roomCallbackL: Callback = object : Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
PopulateDbAsyncTask(instance).execute()
}
}
private class PopulateDbAsyncTask(db: NoteDatabase) : AsyncTask<Void, Void, Void>() {
private val noteDao: NoteDao = db.noteDao()
override fun doInBackground(vararg voids: Void): Void? {
noteDao.insert(Note("Title1", "Description1", 1))
noteDao.insert(Note("Title2", "Description2", 2))
noteDao.insert(Note("Title3", "Description3", 3))
return null
}
}
}
}
NoteRepository
package com.leaf76.architectureexample
import android.app.Application
import android.os.AsyncTask
import androidx.lifecycle.LiveData
class NoteRepository(application: Application) {
// The lateinit avoid Nullable
private var noteDao: NoteDao
private var allNotes: LiveData<List<Note>>
init {
val database = NoteDatabase.getInstance(application.applicationContext)
noteDao = database.noteDao()
allNotes = noteDao.getAllNotes()
}
fun insert(note: Note) {
InsertNoteAsyncTask(noteDao).execute(note)
}
fun update(note: Note) {
UpdateNoteAsyncTask(noteDao).execute(note)
}
fun delete(note: Note) {
DeleteNoteAsyncTask(noteDao).execute(note)
}
fun deleteAllnotes() {
DeleteAllNotesAsyncTask(noteDao).execute()
}
fun getAllNotes(): LiveData<List<Note>> {
return allNotes
}
companion object {
// Insert note
private class InsertNoteAsyncTask(var noteDao: NoteDao) :
AsyncTask<Note, Void, Void>() {
override fun doInBackground(vararg notes: Note): Void? {
noteDao.insert(notes[0])
return null
}
}
// Update note
private class UpdateNoteAsyncTask(var noteDao: NoteDao) :
AsyncTask<Note, Void, Void>() {
override fun doInBackground(vararg notes: Note): Void? {
noteDao.update(notes[0])
return null
}
}
// Delete note
private class DeleteNoteAsyncTask(var noteDao: NoteDao) :
AsyncTask<Note, Void, Void>() {
override fun doInBackground(vararg notes: Note): Void? {
noteDao.delete(notes[0])
return null
}
}
// Delete all note
private class DeleteAllNotesAsyncTask(var noteDao: NoteDao) :
AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg voids: Void): Void? {
noteDao.deleteAllNotes()
return null
}
}
}
}
NoteViewModel
package com.leaf76.architectureexample
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
class NoteViewModel(application: Application) : AndroidViewModel(application) {
private var repository: NoteRepository = NoteRepository(application)
private var allNotes: LiveData<List<Note>> = repository.getAllNotes()
fun insert(note: Note){
repository.insert(note)
}
fun update(note:Note){
repository.update(note)
}
fun delete(note: Note){
repository.delete(note)
}
fun deleteAllNotes(){
repository.deleteAllnotes()
}
fun getAllNotes(): LiveData<List<Note>>{
return allNotes
}
}
MainActivity
package com.leaf76.architectureexample
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
class MainActivity : AppCompatActivity() {
private val TAG: String = "MainActivity"
private lateinit var noteViewModel: NoteViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.i(TAG,"MainActivity entry on create")
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
Log.i(TAG,"Get note view model")
noteViewModel.getAllNotes().observe(this, Observer<List<Note>> {
Toast.makeText(this,"onChanged",Toast.LENGTH_LONG).show()
})
Log.i(TAG, "Get Toast")
}
}
It works!!!
When I remove this instance==null condition, but I still don't know kotlin how to run it on Singleton pattern.
// static parameters
companion object {
private lateinit var instance: NoteDatabase
fun getInstance(context: Context): NoteDatabase {
if (instance == null) {
synchronized(NoteDatabase::class.java) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java, "note_database"
)
.fallbackToDestructiveMigration()
.addCallback(roomCallbackL)
.build()
}
}
return instance
}
to
// static parameters
companion object {
private lateinit var instance: NoteDatabase
fun getInstance(context: Context): NoteDatabase {
synchronized(NoteDatabase::class.java) {
instance = Room.databaseBuilder(
context.applicationContext,
NoteDatabase::class.java, "note_database"
)
.fallbackToDestructiveMigration()
.addCallback(roomCallbackL)
.build()
}
return instance
}
I am learning databinding with mvvm but I am getting following errors I did not know what is the main problem.
DataBinderMapperImpl.java:9: error: cannot find symbol
import gahfy.net.databinding.ActivityPostListBindingImpl;
^
symbol: class ActivityPostListBindingImpl
location: package gahfy.net.databinding
error: [kapt] An exception occurred: android.databinding.tool.util.LoggedErrorException: Found data binding error(s):
[databinding] {"msg":"cannot find method getLoadingVisibility() in class gahfy.net.ui.post.PostListViewModel","file":"C:\\Users\\Edgar\\Documents\\MVVMPosts\\app\\src\\main\\res\\layout\\activity_post_list.xml","pos":[{"line0":22,"col0":37,"line1":22,"col1":68}]}
error: cannot find symbol
import gahfy.net.databinding.ActivityPostListBindingImpl;
^
symbol: class ActivityPostListBindingImpl
location: package gahfy.net.databinding
cannot find method getLoadingVisibility() in class gahfy.net.ui.post.PostListViewModel
what I have tried invalidate cache restart and rebuild and clean project it did not helped at all
below activity_post_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="gahfy.net.ui.post.PostListViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:mutableVisibility="#{viewModel.getLoadingVisibility()}" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/post_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:adapter="#{viewModel.getPostListAdapter()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
below PostListActivity.kt
import android.os.Bundle
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import gahfy.net.R
import com.google.android.material.snackbar.Snackbar;
import gahfy.net.databinding.ActivityPostListBinding
class PostListActivity: AppCompatActivity() {
private lateinit var binding: ActivityPostListBinding
private lateinit var viewModel: PostListViewModel
private var errorSnackbar: Snackbar? = null
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_post_list)
binding.postList.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
viewModel = ViewModelProviders.of(this).get(PostListViewModel::class.java)
viewModel.errorMessage.observe(this, Observer {
errorMessage -> if(errorMessage != null) showError(errorMessage) else hideError()
})
binding.viewModel = viewModel
}
private fun showError(#StringRes errorMessage:Int){
errorSnackbar = Snackbar.make(binding.root, errorMessage, Snackbar.LENGTH_INDEFINITE)
errorSnackbar?.setAction(R.string.retry, viewModel.errorClickListener)
errorSnackbar?.show()
}
private fun hideError(){
errorSnackbar?.dismiss()
}
}
below PostListViewModel.kt
class PostListViewModel:BaseViewModel(){
#Inject
lateinit var postApi: PostApi
private val loadingVisibility: MutableLiveData<Int> = MutableLiveData()
val errorMessage:MutableLiveData<Int> = MutableLiveData()
val errorClickListener = View.OnClickListener { loadPosts() }
private val postListAdapter: PostListAdapter = PostListAdapter()
private lateinit var subscription: Disposable
init{
loadPosts()
}
private fun loadPosts(){
subscription = postApi.getPosts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe { onRetrievePostListStart() }
.doOnTerminate { onRetrievePostListFinish() }
.subscribe(
// Add result
{ result -> onRetrievePostListSuccess(result) },
{ onRetrievePostListError() }
)
}
private fun onRetrievePostListStart(){
loadingVisibility.value = View.VISIBLE
errorMessage.value = null
}
private fun onRetrievePostListFinish(){
loadingVisibility.value = View.GONE
}
private fun onRetrievePostListSuccess(postList:List<Post>){
postListAdapter.updatePostList(postList)
}
private fun onRetrievePostListError(){
errorMessage.value = R.string.post_error
}
override fun onCleared() {
super.onCleared()
subscription.dispose()
}
}
below BindingAdapters.kt
#BindingAdapter("mutableText")
fun setMutableText(view: TextView, text: MutableLiveData<String>?) {
val parentActivity:AppCompatActivity? = view.getParentActivity()
if(parentActivity != null && text != null) {
text.observe(parentActivity, Observer { value -> view.text = value?:""})
}
#BindingAdapter("mutableVisibility")
fun setMutableVisibility(view: View, visibility: MutableLiveData<Int>?) {
val parentActivity:AppCompatActivity? = view.getParentActivity()
if(parentActivity != null && visibility != null) {
visibility.observe(parentActivity, Observer { value -> view.visibility = value?:View.VISIBLE})
}
}
#BindingAdapter("adapter")
fun setAdapter(view: RecyclerView, adapter: RecyclerView.Adapter<*>) {
view.adapter = adapter
}
}
It's about your databinding usage in xml.
1.Your used variable must be public or a have public getter.
2.If you want use public variable just use it name (without get).
So you must make this changes in this lines.
private val loadingVisibility: MutableLiveData<Int> = MutableLiveData()
private val postListAdapter: PostListAdapter = PostListAdapter()
To
val loadingVisibility: MutableLiveData<Int> = MutableLiveData()
val postListAdapter: PostListAdapter = PostListAdapter()
And
app:mutableVisibility="#{viewModel.getLoadingVisibility()}"
app:adapter="#{viewModel.getPostListAdapter()}"
To
app:mutableVisibility="#{viewModel.loadingVisibility}"
app:adapter="#{viewModel.postListAdapter}"
BindAdapters
class BindAdapters {
companion object {
#BindingAdapter("mutableText")
fun setMutableText(view: TextView, text: MutableLiveData<String>?) {
val parentActivity: AppCompatActivity? = view.getParentActivity()
if (parentActivity != null && text != null) {
text.observe(parentActivity, Observer { value -> view.text = value ?: "" })
}
}
#BindingAdapter("mutableVisibility")
fun setMutableVisibility(view: View, visibility: MutableLiveData<Int>?) {
val parentActivity: AppCompatActivity? = view.getParentActivity()
if (parentActivity != null && visibility != null) {
visibility.observe(
parentActivity,
Observer { value -> view.visibility = value ?: View.VISIBLE })
}
}
#BindingAdapter("adapter")
fun setAdapter(view: RecyclerView, adapter: RecyclerView.Adapter<*>) {
view.adapter = adapter
}
}
}
I am trying to implement TableLayout on ViewPager but i can not use method setupWithViewPager because android studio says that it is unresolved reference.
This TableLayout and ViewPager should be implemented in fragment (AboutFragment.kt)
My ViewPager works perfectly fine without TabLayout, I mean i can swipe between fragments.
Does somebody have solution?
Here is my AboutFragment:
package hr.ferit.brunozoric.taskie.ui.fragments
import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import hr.ferit.brunozoric.taskie.R
import hr.ferit.brunozoric.taskie.ui.adapters.ViewPagerAdapter
import hr.ferit.brunozoric.taskie.ui.fragments.base.BaseFragment
import kotlinx.android.synthetic.main.fragment_about.*
class AboutFragment: BaseFragment() {
override fun getLayoutResourceId(): Int {
return R.layout.fragment_about
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupPager()
}
private fun setupPager() {
viewPager.adapter = ViewPagerAdapter(fragmentManager!!)
tabLayout.setupWithViewPager(viewPager) // I have error in this line :(
}
companion object{
fun newIstance(): Fragment {
return AboutFragment()
}
}
}
Here is my ViewPagerAdapter:
package hr.ferit.brunozoric.taskie.ui.adapters
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import hr.ferit.brunozoric.taskie.ui.fragments.AboutAplicationFragment
class ViewPagerAdapter(manager :FragmentManager) : FragmentStatePagerAdapter(manager) {
companion object{
const val NUM_OF_PAGES =2
const val PAGE_ONE_TITLE = "About Application"
const val PAGE_TWO_TITLE = "About Author"
}
private val frags = mutableListOf<Fragment>(AboutAplicationFragment(),AboutAplicationFragment())
private val titles = mutableListOf(PAGE_ONE_TITLE, PAGE_TWO_TITLE)
override fun getItem(position: Int): Fragment {
return frags[position]
}
override fun getPageTitle(position :Int) : String{
return titles[position]
}
override fun getCount(): Int {
return NUM_OF_PAGES
}
}
Here is XML file with ViewPager and TabLayout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/tabLayout"
/>
<TableLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
/>
</RelativeLayout>
You have used <TableLayout> instead of <TabLayout>.