How can I change the fonts in android using Kotlin? - android

I am try change the font, but not working. Are returning "null" being that I set the value in the XML and also in the code.
Kotlin Code
val typeFace = Typeface.createFromAsset(tvThanks.context.assets, "dinpro_medium.ttf")
tvThanks.setTypeface(typeFace)
<TextView
android:id="#+id/tvThanks"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/text_here"/>
ERROR
java.lang.IllegalStateException: tvThanks must not be null
at br.com.adrianofpinheiro.testesantander.fragment.ContatoEnviadoFragment.onCreate(ContatoEnviadoFragment.kt:21)

Your fragment should have the context property without getting from the tvThanks.
I think you can try doing this inside the onCreateView of your fragment
val typeFace = Typeface.createFromAsset(context.assets, "dinpro_medium.ttf")
tvThanks!!.setTypeface(typeFace)

class Photos : Fragment() {
private lateinit var rootView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
rootView = inflater.inflate(R.layout.skeleton_photos_tab, container, false)
return rootView
}
}
now you can do this.
rootView.tvThanks.setTypeface(typeFace)

Related

Android Studio: Set Text in fragment

I've recently picked up an Android Studio project I started a year ago in Kotlin.
It features three fragments that can be navigated through by a bottom navigation bar.
Now, to break my current issue down to a simple example that even doesn't work for me:
Given there's a the editText object exercise in fragment_home.xml and I want to call and alter it in HomeFragment.kt.
I checked every source of advice I could find from Google & Stackoverflow and came up with the following code in HomeFragment.kt (partially pre-coded by AndroidStudio):
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
val view: View = inflater!!.inflate(R.layout.fragment_home,container,false)
view.exercise.setText("This is an exceptionally hardcoded string")
The last line stands for every object I tried to reach. I also tried onClickListening for buttons like so:
val btnNewExercise = view.findViewById<Button>(R.id.btn_new_exercise)
btnNewExercise.setOnClickListener {view
Toast.makeText(view.context, "New exercise will be generated", Toast.LENGTH_SHORT).show()
println("Generated a new exercise")
}
but nothing happens when I start the app/ hit the buttons - I seem to can't get through to the actual view's objects to access them. Even ran into NullPointerExceptions on my way to a solution.
I could supply the fragment and layout files if needed - just thought this way it might be easier at first.
If anybody could tell me where I'm wrong I'd be really grateful! Thanks in advance!
You inflated the layout twice.
Remove this. You already inflated the layout using view binding in the FragmentHomeBinding.inflate... call
val view: View = inflater!!.inflate(R.layout.fragment_home,container,false)
and replace
view.exercise.setText("This is an exceptionally hardcoded string")
with (using binding
binding.exercise.setText("This is an exceptionally hardcoded string")
then the last line on your onCreateView should be
return binding.root
Note: You should have these class properties:
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
So it will look like this:
//move your view model as a class property so it will be accessible by other class methods
private val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!//transform to immutable
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
//use the immutable view binding property
binding.exercise.setText("This is an exceptionally hardcoded string")
return binding.root
}
For more info, read view binding
Try this solution.
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.exercise.text="This is an exceptionally hardcoded string"
binding.btnNewExercise.setOnClickListener {
Toast.makeText(view.context, "New exercise will be generated", Toast.LENGTH_SHORT).show()
println("Generated a new exercise")
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
You need to return the view you made in the OnCreateView .

About viewbinding

I would like to ask about ViewBinding.
The official
buildFeatures{
viewBinding = true
}
but it does not work.
Here is an example code.
Layout Code
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
android:clickable="true"
android:focusable="true"
android:tint="#color/white"
android:src="#drawable/ic_add"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
Kotlin Code
val view = inflater.inflate(R.layout.fragment_list, container, false)
view.floatingActionButton.setOnClickListener { }
Is there any solution to this problem?
I don't know why it is not working.
Android studio Vierson4.1.2
Gradle Viesion 6.5
You need to use as a parent in layout.xml
Example:- my_layout.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">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="#dimen/_4sdp">
<TextView
android:id="#+id/scanner"
android:layout_width="#dimen/_200sdp"
android:layout_height="#dimen/_200sdp"
android:layout_centerInParent="true"
app:squaredFinder="true" />
</RelativeLayout>
</layout>
and in Kotlin.
val binding = DataBindingUtil.inflate(android.view.LayoutInflater.from(context), R.layout.my_layout, null, false);
This is how you enable view binding
private var _binding: FragmentListBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentListBinding.inflate(inflater, container, false)
binding.floatingActionButton.setOnClickListener { }
return binding.root
Fragments outlive their views. Make sure you clean up any references to the binding class instance in the fragment's onDestroyView() method.
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
For more details, read.
Try like this.
class BaseActivity : AppCompatActivity(){
private lateinit var binding: (YourActivityBinding)
super.onCreate(savedInstanceState){
binding = YourActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.floatingActionButton.setOnClickListener (View.OnClickListener{
})
}
}
Try this. In Your Gradle (Modul):
android{
.
.
.
buildFeatures {
dataBinding true
}
}
After sync, in Your XML File, try to push (ALT+Enter) on your layout parent and choice
Convert To Data Binding
Now in your Activity
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
}
}
Or in Your fragment:
class BlankFragment: Fragment() {
private lateinit var binding: FragmentBlankBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = FragmentBlankBinding.inflate(inflater)
return binding.root
}
from now, for binding view, you should write something like this:
binding.textView.text = "test"
Thank you for your wonderful answers.
I had forgot to create a binding class.
I was able to solve the problem successfully and the error has been resolved.
ADD Code
private var _binding: FragmentListBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
_binding = FragmentListBinding.inflate(inflater, container, false)
binding.floatingActionButton.setOnClickListener {
}
return binding.root
}

Can't get access to Views by DataBinding or Android Extensions

I can't change value of Views by DataBinding or by Android Extensions, but it works by 'traditional way' (findViewById). Also, it throws NPE when I try by Android Extensions' way without safe call operator.
HourlyFragment.kt
class HourlyFragment : Fragment() {
private lateinit var binding: FragmentHourlyBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
var rootView = inflater.inflate(R.layout.fragment_hourly, container, false)
binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_hourly, container, false
)
// doesn't work
//binding.tvHourly.text = "HOURLY!"
val tvHourly : TextView = rootView.findViewById(R.id.tv_hourly)
tvHourly.setText("HOURLY!!")
// doesn't work, without safe call operator throws NullPointerException
//tv_hourly?.text = "HOURLY!!!"
return rootView
}
}
fragment_hourly.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.HourlyFragment">
<TextView
android:id="#+id/tv_hourly"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="hourly fragment" />
</FrameLayout>
</layout>
Currently you are inflating your views twice and that's causing all the issues I believe, so instead just inflate your views once and see if it solves your issue
Try the following
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// var rootView = inflater.inflate(R.layout.fragment_hourly, container, false)
binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_hourly, container, false
)
binding.tvHourly.text = "HOURLY!"
// val tvHourly : TextView = rootView.findViewById(R.id.tv_hourly)
tvHourly.setText("HOURLY!!")
return binding.root
}
Why your data binding doesn't work:
You are manually inflating with the line
var rootView = inflater.inflate(R.layout.fragment_hourly, container, false)
but then you use data binding to inflate another copy of this hierarchy in the next line of code. You then return the first layout from onCreateView, throwing away your second inflated data binding layout. You changed the text of the view in the data binding layout that you then threw away.
Why your Android Extensions doesn't work:
You can't use the synthetic view references before onCreateView() returns, because the Fragment still doesn't have any view attached to it for the synthetic property to use to find the child view.
You should be modifying view content in onViewCreated() instead.
By the way, Android Extensions is deprecated and should no longer be used.
In a more concise and more readable way:
private lateinit var binding: FragmentHourlyBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHourlyBinding.inflate(
inflater, container, false
).apply {
tvHourly.text = "HOURLY!"
}
return binding.root
}

How to fetch resource id in fragment using kotlin in android?

I tried to this code which is mention below, but getting crash during run time. The error occurred is Android Run time:
FATAL EXCEPTION: main Process: com.root.specialbridge, PID: 17706 kotlin.KotlinNullPointerException at com.root.specialbridge.fragments.profile_fragment.WallFragments.initializeView(WallFragments.kt:49)
class WallFragments : Fragment(){
private var wallAdapter: WallAdapter? = null
private var wall_recycler: RecyclerView? = null
private val wallArrayList: ArrayList<Wall>? = null
private var mainlayout: LinearLayout? = null
private var no_result_found_layout: RelativeLayout? = null
private var userProfileWallInterface: UserProfileWallInterface? = null
internal var wallActivityBeanse: MutableList<WallActivityBeans> = ArrayList()
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater!!.inflate(R.layout.wall_fragments, container, false)
userProfileWallInterface = UserProfileWallPresentation(activity, this)
initializeView()
wallAdapter = WallAdapter(activity, wallActivityBeanse)
wall_recycler!!.adapter = wallAdapter
return view
}
fun initializeView() {
wall_recycler = view!!.findViewById(R.id.wall_recycler_id) as RecyclerView
mainlayout = view!!.findViewById(R.id.mainlayout) as LinearLayout
no_result_found_layout = view!!.findViewById(R.id.no_result_found_layout) as RelativeLayout
wall_recycler!!.layoutManager = LinearLayoutManager(activity)
wall_recycler!!.setHasFixedSize(true)
if (AuthPreference(activity).isGetMemberProfile) {
userProfileWallInterface!!.getMemberProfileWall(view!!)
} else {
userProfileWallInterface!!.getUserProfileWall(AuthPreference(activity).token, AuthPreference(activity).user.id, view!!)
}
}
companion object {
val instance: WallFragments
get() = WallFragments() }}
Add
apply plugin: 'kotlin-android-extensions'
in the app level gradle file and
import
import kotlinx.android.synthetic.main.fragment_your_fragment_name.view.*
in the onCreateView of your fragment (e.g. if the id of your textview is textView)
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
val view = inflater!!.inflate(R.layout.fragment_splashfragment, container, false)
view.textView.text = "hello" //add your view before id else getting nullpointer exception
return view
}
UPDATE:
declare viewOfLayout in your class instead of view.
class yourfragment:Fragment(){
private lateinit var viewOfLayout: View
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
viewOfLayout = inflater!!.inflate(R.layout.fragment_splashfragment, container, false)
viewOfLayout.textView.text = "hello" //add your view before id else will get nullpointer exception
return viewOfLayout
}
}
Introducing Kotlin Android Extensions.
You do not have to use findViewById anymore. Using this plugin you can use the UI component directly as a global field. Supported in Activities, fragments and views.
Example,
To refer text view from the layout below,
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/hello"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, MyActivity"/>
</android.support.constraint.ConstraintLayout>
in activity you can simply write,
// Using R.layout.activity_main from the main source set
import kotlinx.android.synthetic.main.activity_main.*
class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Instead of findViewById(R.id.hello) as TextView
hello?.setText("Hello, world!")
}
}
in fragments,
// Using R.layout.fragment_content from the main source set
import kotlinx.android.synthetic.main.fragment_content.*
class ContentFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
inflater.inflate(R.layout.fragment_content, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Instead of view.findViewById(R.id.hello) as TextView
hello?.setText("Hello, world!")
}
}
and for views,
// Using R.layout.item_view_layout from the main source set
import kotlinx.android.synthetic.main.item_view_layout.*
class ItemViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindData(data: String) {
// Instead of itemView.findViewById(R.id.hello) as TextView
itemView.hello?.setText(data)
}
}
And, you should not use !! everywhere, unless you want NullPointerException explicitly.
Instead use anyone from the following:
Do null check with safe call - ?., Eg. nullableVariable?.method()
Use non-null object using ?.let{ }, Eg. nullableVariable?.let { it.method() }
Supplying a backup value for the nullable variable using elvis operator - ?:, Eg. nullableVariable ?: <backupValue>.
Read more about Null Safety in Kotlin.
Initialization of view in fragment :
wall_recycler=view.findViewById<RecyclerView>(R.id.wall_recycler_id)
mainlayout = view.findViewById<LinearLayout>(R.id.mainlayout)
The problem is that you are accessing it too soon. requireView() and view returns null in onCreateView.I have find all views in onViewCreated().
Try doing it in the onViewCreated method:
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
wall_recycler=requireView().findViewById<RecyclerView>(R.id.wall_recycler_id)
mainlayout = requireView().findViewById<LinearLayout>(R.id.mainlayout)
mainlayout.setOnClickListener { Log.d(TAG, "onViewCreated(): hello world");}
}

Caused by: kotlin.TypeCastException: null cannot be cast to non-null type android.widget.TextView in fragments

class DashBoardFragment : Fragment() {
private var recyclerView : RecyclerView?=null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater!!.inflate(R.layout.fragment_dash_board, container, false)
initComponents(view )
return view
}
private fun initComponents(View view) {
var textView : TextView = view?.findViewById(R.id.recyclerView) as TextView
textView.setText("hello world")
}
when changing into recycler its showing same problem appreciate if you help to me
Well, how about adding more details. Like, what are you trying to accomplish, how are you doing it, what difficulties you have found with the approach, another approaches you have tried, etc. In summary, without code isn't a good question neither is with just code. Search for the balance!
Try moving the code in the initComponents function to the onCreateView function. The error might occur because recyclerView id is not ready until the View is created.
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater!!.inflate(R.layout.fragment_dash_board, container, false)
var textView : TextView = view?.findViewById(R.id.recyclerView) as TextView
textView.setText("hello world")
return view
}

Categories

Resources