Skip to content

Instantly share code, notes, and snippets.

@paulcoding810
Last active September 11, 2022 05:19
Show Gist options
  • Save paulcoding810/4f928f4a77a84910e45f37057c11bdfa to your computer and use it in GitHub Desktop.
Save paulcoding810/4f928f4a77a84910e45f37057c11bdfa to your computer and use it in GitHub Desktop.
android minor knowledges

grasp

  • collect minor codes ...

val message = snapshot.value as Map<*, *>

adapter scroll-button vs reaction

enum property

enum class DateMark(val value: String) {
    TODAY("Today"),
    YESTERDAY("Yesterday")
}

share viewmodel betweeb activity and fragment

Fragment.activityViewModels() == ComponentActivity.viewModels()

loop Runnable

    Handler(Looper.getMainLooper()).also {
      it.post(object : Runnable {
        override fun run() {
            it.postDelayed(this, 300)

bring to front

binding.root.bringChildToFront(binding.appbar)

animation holder

        val alpha = PropertyValuesHolder.ofFloat("alpha", 0.3f, 1f)
 val objectAnimator1: ObjectAnimator =
            ObjectAnimator.ofPropertyValuesHolder(tvName, alpha, scaleX, scaleY)
 val animatorSet = AnimatorSet()
        animatorSet.playTogether(objectAnimator1, objectAnimator2)
        animatorSet.interpolator = AccelerateInterpolator()
        animatorSet.duration = 2000
        animatorSet.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animator: Animator) {}
            override fun onAnimationEnd(animator: Animator) {
                MainActivity.startAction(this@SplashScreen1)
                finish()
            }
        animatorSet.start()

** fun startAction(activity: Activity) { val intent = Intent(activity, MainActivity::class.java) activity.startActivity(intent) activity.overridePendingTransition( R.anim.fade_in, R.anim.fade_out ) }

style attrs

val ta = context.obtainStyledAttributes(attrs, R.styleable.RecordButton2) try { val text = ta.getString(R.styleable.RecordButton2_text) val drawableId = ta.getResourceId(R.styleable.RecordButton2_image, 0) if (drawableId != 0) { val drawable = AppCompatResources.getDrawable(context, drawableId) btn.setImageDrawable(drawable) } tv.text = text } finally { ta.recycle() }

custom view

constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super( context, attrs, defStyle ) inflate(context, R.layout.layout_button_record_merge, this) btn = findViewById(R.id.btn_record) tv = findViewById(R.id.txt_record_info)

layout change

android:animateLayoutChanges="true"

animation

ScaleAnimation animation = new ScaleAnimation( 1.15f, 1, 1.15f, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mCardsContainerView.setAnimation(animation); animation.setDuration(100); animation.setRepeatCount(2); animation.setFillAfter(true); animation.setFillBefore(false); animation.setRepeatMode(Animation.REVERSE); animation.start();

bind context

class Builder (val multiplier: Int) { fun invokeStuff(action: (Builder.() -> Unit)) { this.action() }

if 2 val 4 case

val x= 1
val y=1
println(x shl 1 or y)

sum

data.sumOf { it.second.size }

list to map

listMember.associateBy { member -> member.id }

disable night mode

 AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)

TextView ellipsize

   <TextView
            android:ellipsize="end"
            android:singleLine="true"

rounded Bottomsheet

class MyBottomSheet: BottomSheetDialogFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(STYLE_NORMAL, R.style.AppBottomSheetDialogTheme) }

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val view = inflater.inflate(R.layout.bottomsheet, container, false)
    return view
}

}

<style name="AppBottomSheetDialogTheme" parent="Theme.Design.Light.BottomSheetDialog">
    <item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>

<style name="AppModalStyle" parent="Widget.Design.BottomSheet.Modal">
    <item name="android:windowIsFloating">false</item>
    <item name="android:background">@drawable/bottomsheet_radius_border</item>
</style>

setId

res/values/ids.xml

update numeric value

washingtonRef.update("population", FieldValue.increment(-50))

adapter item added listener

adapter.registerAdapterDataObserver

update array

washingtonRef.update("regions", FieldValue.arrayUnion("greater_virginia")) washingtonRef.update("regions", FieldValue.arrayRemove("east_coast"))

Update fields in nested objects

https://firebase.google.com/docs/firestore/manage-data/add-data?authuser=0#update_fields_in_nested_objects db.collection("users").document("frank") .update(mapOf( "age" to 13, "favorites.color" to "Red" )) db.collection('users').doc('frank').update({ [favorites.${key}.color]: true });

layout param for binding

Ìnlate with viewgroup

layerlist padding

long click on recyclerview

https://stackoverflow.com/questions/17879743/get-parents-view-from-a-layout viewHolder.itemView.setOnLongClickListener { v: View -> Log.d(TAG, "onBindViewHolder: view=${v.parent}") mItemLongClickListener!!.invoke(v.parent as ViewGroup) true }

dialog

    val dialog = Dialog(requireContext())
    
    reactionBinding.layoutReact.setOnClickListener {
        dialog.dismiss()
    }

val param = reaction.layoutParams as LinearLayout.LayoutParams param.setMargins(0, marginTop, 0, 0) reaction.layoutParams = param

    dialog.apply {
        setContentView(reactionBinding.root)
        setOnDismissListener {
            message.alpha = 1f
        }
        setCancelable(true)

        window?.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

window?.attributes?.gravity = Gravity.TOP window?.setBackgroundDrawable(ColorDrawable(android.R.color.transparent)) //drawablerresource(android.R.color.transparent)

        show()
    }

content uri to stream

getContentResolver().openInputStream(uri)

holder itemview, holder position

            val adapterPosition = viewHolder.absoluteAdapterPosition
            mItemClickListener.invoke(v, adapterPosition)

remote repo

git config --get remote.origin.url

flow

DO NOT USE shareIn or stateIn in a function DO USE shareIn or stateIn in a property

Flow.stateIn caches and replays the last emitted item to a new collector.

SharingStarted.Eagerly policy to listen for updates even if there are no collectors.

data is a state (use StateFlow then) or an event (use SharedFlow).

StateFlow takes a default value through the constructor and emits it immediately when someone starts collecting, while a SharedFlow takes no value and emits nothing by default.

when using a flow the data is produced within the stream while in channels the data is produced in of the stream.

cold flow only emits data when it is collected (or consumed).

terminal operatoer - collect - subscribe-consumer hotflow->The WhileSubscribed sharing policy is used to cancel the upstream flow when there are no collectors. In this way, we avoid wasting resources when no one is interested in location updates.

The main difference between these APIs is that the StateFlow interface allows you to access the last emitted value synchronously by reading its value property. That’s not the case with SharedFlow.

Flows are sequential producer cannot emit values from a different CoroutineContext

hide on scroll

    nested.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, _, _, _ ->
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if(nested.canScrollVertically(-1)){
                home.appbar.elevation = 4f
            }else{
                home.appbar.elevation = 0f
            }
        }
    })

activity onbackpress

moveTaskToBack(true)

transition

    super.onCreate(savedInstanceState)
    enterTransition =          TransitionInflater.from(context).inflateTransition(R.transition.slide_bottom)


        activity.overridePendingTransition(
            R.anim.fade_in,
            R.anim.fade_out
        )

check URI file

    final Uri uri = Uri.parse(path);
    final String scheme = uri.getScheme();
    if ("file".equals(scheme)) {
        path = uri.getPath();

glide to bitmap

        val futureTarget = Glide.with(this)
            .asBitmap()
            .load(imageUrl)
            .submit()
        val bitmap = futureTarget.get()
        notificationBuilder.setLargeIcon(bitmap)

width - height ratio

     <Button android:layout_width="wrap_content"
               android:layout_height="0dp"
               app:layout_constraintDimensionRatio="1:1" />

constraint circle

<Button android:id="@+id/buttonA" ... /> <Button android:id="@+id/buttonB" ... app:layout_constraintCircle="@+id/buttonA" app:layout_constraintCircleRadius="100dp" app:layout_constraintCircleAngle="45" />

constraint bias

<androidx.constraintlayout.widget.ConstraintLayout ...> <Button android:id="@+id/button" ... app:layout_constraintHorizontal_bias="0.3" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </>

corner background

mutidex

Too many field references: 131000; max is 65536. You may try using --multi-dex option

assest file json

// assests/data.json InputStream is = application.getAssets().open("data.json"); Scanner s = new Scanner(is).useDelimiter("\A"); return s.hasNext() ? s.next() : "";

simple request

// https://mkyong.com/java/okhttp-how-to-send-http-requests/ public class NetworkUtils { private static final OkHttpClient mClient = new OkHttpClient();

public static String getProductListFromURL(String urlStr) throws IOException {
    Request request = new Request.Builder()
                        .url(urlStr)
                        .build();

    try (Response response = mClient.newCall(request).execute()) {
        if(response.isSuccessful()){
            return response.body().string();
        }else{
            throw new IOException("Unexpected response code " + response.code());
        }
    }
}

}

grep info

adb shell dumpsys package com.google.android.gms | grep version

firestore boolean field

@field:JvmField isMe: Boolean

internal storage

requireContext().filesDir.absolutePath --> /data/user/0/com.goldenowl.paul.ecommerce/files

set background

this.setBackgroundColor(Color.parseColor("#C1FF0000"))

thread

            Thread(Runnable {
                for (i in 1..50) {
                    BitmapFactory.decodeStream(
                        resources.assets.open(
                            "img/${
                                resources.assets.list(
                                    "img"
                                )!![Random.nextInt(
                                    1, resources.assets.list(
                                        "img"
                                    )!!.size
                                )]
                            }"
                        )
                    ).also { bitmap ->
                        runOnUiThread {
                            adapter.addData(MyNSFWBean(bitmap))
                        }
                    }
                }
            }).start()

fragment manager

supportFragmentManager: use in ACTIVITY parentFragmentManager: use in FRAGMENT childFragmentManager: use in Nested Fragment

dp to px

        val iconMarginPx =
            TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 8F, resources.displayMetrics
            )
                .toInt()

val iconMarginPx = resources.getDimension(R.dimen.popup_icon_margin).toInt()


public static int dip2px(Context context, float dpValue) {
    final float scale = context.getApplicationContext().getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
}

fragmentmanager

requireActivity().supportFragmentManager ~ parentFragmentManager.

toobject vs toobjects

            val task = db.collection("channels").whereArrayContains("listUser", userId).get().await()
            val list: List<Channel> = task.toObjects(Channel::class.java)

            val task = db.collection("channels").document(id).get().await()
            val chnnel = task.toObject(Channel::class.java)

arrayadapter

ArrayAdapter is an adapter for a ListView. For a RecyclerView you have to use a RecyclerView.Adapter

horizontal scrollview

<HorizontalScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scrollbars="horizontal"
    >

fragment context

onViewCreated(view: View ... --> view.context insteadof requireContext()

check fragment

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val id = arguments?.getLong(ARG_ID)
    if (id == null) {
        parentFragmentManager.popBackStack()
        return
    }

kotlin-android-extensions, get view

https://antonioleiva.com/kotlin-android-extensions/ apply plugin: 'kotlin-android-extensions'

root view

    val root = findViewById<ViewGroup>(android.R.id.content).rootView

full screen

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        window.statusBarColor = getColor(android.R.color.transparent)
        window.navigationBarColor = getColor(android.R.color.transparent)
    }

    moviesRootLayout.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_STABLE or
            SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

splash screen

    val im = findViewById<ImageView>(R.id.SplashScreenImage)
    im.alpha = 0f
    im.animate().setDuration(2000).alpha(1f).withEndAction {
        Log.d("MainActivity", "withEndAction ")
        val intent = Intent(this, MainActivity2::class.java)
        startActivity(intent)
        overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
        finish()
    }

statusbar color

  • noactionbar true ?attr/colorPrimary @android:color/holo_blue_dark

C1 name="android:windowBackground">@android:color/holo_blue_dark

C2 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { window.statusBarColor = getColor(R.color.purple_200) window.navigationBarColor = getColor(R.color.purple_200) window.setBackgroundDrawable(ColorDrawable(getColor(R.color.purple_200))) }

firebase get id before add

    val db = Firebase.firestore.collection("123")
    val doc =db.document()
    doc.set(doc.id)

bubble permission

    startActivity(
        Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS)
            .putExtra(Settings.EXTRA_APP_PACKAGE, "com.example.android.people"))

viewpager2 match parent

ViewBinding.inflate(inflater) to ViewBinding.inflate(inflater, parent, false)

glide downloadonly

withcontext(distpachers.IO){ Glide.downloadonly() }

dependencies

recyclerAdapter vs listAdapter

Recyclerview.Adapter=best if the list is static ListAdapter =best if the list is dynamic

bind viewholder

class ContactViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.chat_item, parent, false) ) { val binding: ChatItemBinding = ChatItemBinding.bind(itemView) }

upload firebase storage

            val uploadTask = result.mapIndexed { index, localMedia ->
                val ref = storageReference.reference.child("messages/$channelId/${localMedia.hashCode()}")
                async {
                    val file = Uri.fromFile(File(localMedia.availablePath))
                    val url = ref.putFile(file)
                        .await()
                        .metadata!!.reference!!.downloadUrl
                        .await().toString()
                    uploadedUrls[index] = url
                }
            }

singleton

class GlideEngine private constructor() companion object { fun createGlideEngine(): GlideEngine { return InstanceHolder.instance } }

tag

val photo = it.getTag(R.id.tag_photo) as Uri?

glide to textview

        Glide.with(holder.binding.message)
            .load(message.photoUri)
            .into(CompoundBottomTarget(holder.binding.message, photoSize, photoSize))

tint

private val tint = object {
    val incoming: ColorStateList = ColorStateList.valueOf(
        ContextCompat.getColor(context, R.color.incoming)
    )
    val outgoing: ColorStateList = ColorStateList.valueOf(
        ContextCompat.getColor(context, R.color.outgoing)
    )
}

        holder.binding.message.run {
            setBackgroundResource(R.drawable.message_outgoing)
            ViewCompat.setBackgroundTintList(this, tint.outgoing)

stackfromend

   val linearLayoutManager = LinearLayoutManager(view.context).apply {
        stackFromEnd = true
    }

timestamp

val timestamp = System.currentTimeMillis()
println(Date())
println(Date().time)
println(timestamp)
println(Date(timestamp))

listadapter itemId

override fun getItemId(position: Int): Long {
    return getItem(position).id
}

slide

    enterTransition =
    TransitionInflater.from(context).inflateTransition(R.transition.slide_bottom)

binding

class MainFragment : Fragment(R.layout.main_fragment) {

private val binding by viewBindings(MainFragmentBinding::bind)

commitNow

        supportFragmentManager.commitNow {
            replace(R.id.container, MainFragment())
        }

topic

https://developer.android.com/guide/topics/ui/bubbles

markdown

https://github.dev/cometchat-pro/android-kotlin-chat-app

disableTooltip

fun BottomNavigationView.disableTooltip() { val content: View = getChildAt(0) if (content is ViewGroup) { content.forEach { it.setOnLongClickListener { return@setOnLongClickListener true } // disable vibration also it.isHapticFeedbackEnabled = false } } }

typealias

typealias ChatThreadListener = (List) -> Unit private val listeners = mutableListOf()

new instance

    fun newInstance(channel: Channel) =
        ChatFragment().apply {
            arguments = Bundle().apply {
                putParcelable(CHANNEL, channel)
            }
        }

debug option

    debug {
        debuggable true
        applicationIdSuffix ".debug"
        resValue "string", "app_name", "LibreTube Debug"
    }

setting intent

https://stackoverflow.com/questions/55961409/any-way-to-go-directly-to-the-enable-usb-debugging-page-in-android https://developer.android.com/reference/android/provider/Settings#constants_1

setOnEditorActionListener

EditText.setOnEditorActionListener { _, actionId, _ ->
    when (actionId) {
        EditorInfo.IME_ACTION_DONE ->
            loginViewModel.login(
                username.text.toString(),
                password.text.toString()
            )
    }
    false
}

binding

        val view = inflater.inflate(R.layout.message, parent, false)
        val binding = MessageBinding.bind(view)

flatMapLatest

LiveData.switchMap = Flow.flatMapLatest

flow

By default, a Flow will restart from the top every time a terminal operator is applied. This is important if the Flow performs expensive work, such as making a network request.

livedata builder - emitSource

val plants: LiveData<List> = liveData<List> { val plantsLiveData = plantDao.getPlants() val customSortOrder = plantsListSortOrderCache.getOrAwait() emitSource(plantsLiveData.map { plantList -> plantList.applySort(customSortOrder) }) }

switchMap

A switchMap applies a given function to the input LiveData (growZone in this case) and returns the transformed result as a LiveData.

val plants: LiveData<List<Plant>> = growZone.switchMap { growZone ->
    if (growZone == NoGrowZone) {
        plantRepository.plants
    } else {
        plantRepository.getPlantsWithGrowZone(growZone)
    }
}

fun getPlantsWithGrowZone(growZone: GrowZone) = plantDao.getPlantsWithGrowZoneNumber(growZone.number) .switchMap { plantList -> liveData { val customSortOrder = plantsListSortOrderCache.getOrAwait() emit(plantList.applyMainSafeSort(customSortOrder)) } }

Executors

class LoggerLocalDataSource @Inject constructor(private val logDao: LogDao) : LoggerDataSource {

private val executorService: ExecutorService = Executors.newFixedThreadPool(4)
private val mainThreadHandler by lazy {
    Handler(Looper.getMainLooper())
}

override fun addLog(msg: String) {
    executorService.execute {
        logDao.insertAll(
            Log(
                msg,
                System.currentTimeMillis()
            )
        )
    }
}

override fun getAllLogs(callback: (List<Log>) -> Unit) {
    executorService.execute {
        val logs = logDao.getAll()
        mainThreadHandler.post { callback(logs) }
    }
}

override fun removeLogs() {
    executorService.execute {
        logDao.nukeTable()
    }
}

}

save image

        val resourceUri = inputData.getString(KEY_IMAGE_URI)
        val bitmap = BitmapFactory.decodeStream(
                resolver.openInputStream(Uri.parse(resourceUri)))
        val imageUrl = MediaStore.Images.Media.insertImage(
                resolver, bitmap, title, dateFormatter.format(Date()))

not interface

data class PlantDetailsCallbacks( val onFabClick: () -> Unit, val onBackClick: () -> Unit, val onShareClick: () -> Unit )

config API

    buildConfigField("String", "UNSPLASH_ACCESS_KEY", "\"" + getUnsplashAccess() + "\"")

buildTypes.each {
    it.buildConfigField 'String', 'API_TOKEN', "\"5ad8ca8b309244d08440fc1ab9f7e0dc\""  //--< Delete this whole block, not needed when you have your own API_KEY
}

nav arguments

private val args: GalleryFragmentArgs by navArgs()

transaction

@Transaction
@Query("SELECT * FROM plants WHERE id IN (SELECT DISTINCT(plant_id) FROM garden_plantings)")
fun getPlantedGardens(): Flow<List<PlantAndGardenPlantings>>

entity

@Entity( tableName = "garden_plantings", foreignKeys = [ ForeignKey(entity = Plant::class, parentColumns = ["id"], childColumns = ["plant_id"]) ], indices = [Index("plant_id")] )

room column name

@ColumnInfo(name = "plant_id") val plantId: String,

pendingbinding

        with(binding) {
            viewModel = PlantAndGardenPlantingsViewModel(plantings)
            executePendingBindings()
        }

setHasFixedSize

    recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view).apply {
        setHasFixedSize(true)
    }

currentTimeMillis

System.currentTimeMillis()

LinkedListrivate val logs = LinkedList()

curl

curl --header "Authorization: key=AAAAKKpZVic:APA91bH4WYWfIHpQ-gwskRGI2lVBpBio7h5kREfBq3eUOBViiYRj8-S5gkB2O60nZzDq5wJ1_9H2Y0TCiNs5JWcLAes_aWeXKcrzPQfSlXFiKaL-tFHEH7fkPo3_vakspJaVudycBDLN"
--header Content-Type:"application/json"
https://fcm.googleapis.com/fcm/send
-d "{"registration_ids":["ABC"]}"

compare branch

https://github.com/googlecodelabs/android-hilt/compare/main...solution

manual navigation

override fun navigateTo(screen: Screens) {
    val fragment = when (screen) {
        Screens.BUTTONS -> ButtonsFragment()
        Screens.LOGS -> LogsFragment()
    }

    activity.supportFragmentManager.beginTransaction()
        .replace(R.id.main_container, fragment)
        .addToBackStack(fragment::class.java.canonicalName)
        .commit()
}

back

override fun onBackPressed() {
    super.onBackPressed()

    if (supportFragmentManager.backStackEntryCount == 0) {
        finish()
    }
}

git clone branch

git clone -b solution https://github.com/googlecodelabs/android-hilt

navigate

    private fun navigateToPlant(plantId: String, view: View) {
        val direction = HomeViewPagerFragmentDirections
            .actionViewPagerFragmentToPlantDetailFragment(plantId)
        view.findNavController().navigate(direction)
    }

DataBindingUtil

return ViewHolder(
        DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.list_item_garden_planting,
            parent,
            false
        )
    )

report drawn

activity?.reportFullyDrawn()

Params:

fragment – if the ViewPager2 lives directly in a Fragment subclass.

class SunflowerPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

request permisssion

private val requestPermissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
    if (isGranted) {
        // FCM SDK (and your app) can post notifications.
    } else {
        // TODO: Inform user that that your app will not show notifications.
    }
}

notification with image

private fun notifyCloudMessage(title: String?, body: String?, imageUrl: Uri?) {
    val notificationId = 201
    var notificationBuilder = NotificationCompat.Builder(this, getString(R.string.channel_cloud_message_id))
        .setSmallIcon(R.mipmap.ic_ecommerce_launcher_round)
        .setContentTitle(title)
        .setContentText(body)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setAutoCancel(true)
    imageUrl?.let {
        val futureTarget = Glide.with(this)
            .asBitmap()
            .load(imageUrl)
            .submit()
        val bitmap = futureTarget.get()
        notificationBuilder.setLargeIcon(bitmap)
    }
    with(NotificationManagerCompat.from(this)) {
        notify(notificationId, notificationBuilder.build())
    }
}

Error: Could not initialize class com.android.sdklib.repository.AndroidSdkHandler

buildscript { repositories { jcenter() google() } dependencies { classpath 'com.android.tools.build:gradle:7.2.0'

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}

}

crashlytics

FirebaseCrashlytics: Settings request failed update this: dependencies { classpath 'com.google.gms:google-services:4.3.8'

NestedScrollView

<androidx.core.widget.NestedScrollView
    android:fillViewport="true"

            android:nestedScrollingEnabled="false" 

statusbar, fitsystemwindow, not collap

appbarlayout: liftonscroll, eleveation =0dp materialtoolbar: elevation=0dp appbarlayout+toolbar: shadow -> elevation appbarlayout = 0

    /* drop down menu*/
    val adapterSize = ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, listSize)
    val adapterColor =
        ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, product.getListColor())
    (binding.menuSize.editText as? AutoCompleteTextView)?.setAdapter(adapterSize)
    (binding.menuColor.editText as? AutoCompleteTextView)?.setAdapter(adapterColor)


    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)


fun formatDate(date: Date): String {
    return SimpleDateFormat("MMMM dd, YYYY").format(date)
}

fun countDate(startDate: Date, endDate: Date): Long {
    val d = endDate.time - startDate.time
    return TimeUnit.DAYS.convert(d, TimeUnit.MILLISECONDS)
}

class BottomSheetWriteReviewAdapter(private val addImageListener: () -> Unit)

                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                val uri = Uri.fromParts("package", requireActivity().packageName, null)
                intent.data = uri
                settingLauncher.launch(intent)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Create channel to show notifications. val channelId = getString(R.string.default_notification_channel_id) val channelName = getString(R.string.default_notification_channel_name) val notificationManager = getSystemService(NotificationManager::class.java) notificationManager?.createNotificationChannel(NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW)) }

var builder = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle(textTitle) .setContentText(textContent) .setPriority(NotificationCompat.PRIORITY_DEFAULT)

font?

5s fun testcorona() { Log.d(TAG, "testcorona") viewModelScope.launch { val time = measureTimeMillis { val job1 = async { delay(5000) Log.d(TAG, "testcorona: job1 callled") } val job2 = async { delay(1000) Log.d(TAG, "testcorona: job2 callled") } job1.await() job2.await() } Log.d(TAG, "testcorona: measureTimeMillis=$time") } }

2 viewholder

Integer.MIN_VALUE

                val debounceJob: Job? = null
                val uiScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
                var lastInput = ""

                    override fun onQueryTextChange(newText: String?): Boolean {
                        debounceJob?.cancel()
                        if (lastInput != newText) {
                            lastInput = newText ?: ""
                            uiScope.launch {
                                delay(500)
                                if (lastInput == newText) {
                                    Log.i("onQueryTextChange", newText!!)
                                    Log.d(CategoryFragment.TAG, "onQueryTextChange: uiScope")
                                    sortViewModel.searchTerm.value = newText
                                }

editText.setSelection(editText.length())

ctrl alt ;

    android:includeFontPadding="false"

Quantity: %1$s cupcakes \n Flavor: %2$s \nPickup date: %3$s \n Total: %4$s \n\n Thank you! getString(R.string.order_details, "12", "Chocolate", "Sat Dec 12", "$24.00")

val price: LiveData<String> = Transformations.map(_price) {
 NumberFormat.getCurrencyInstance().format(it)
}

app:popUpTo="@id/startFragment" popUpToInclusive

val intent = Intent(Intent.ACTION_SEND) .setType("text/plain") .putExtra(Intent.EXTRA_SUBJECT, getString(R.string.new_cupcake_order)) .putExtra(Intent.EXTRA_TEXT, orderSummary)

if (activity?.packageManager?.resolveActivity(intent, 0) != null) { startActivity(intent) }

%d cupcake %d cupcakes getQuantityString(R.plurals.cupcakes, 6, 6)

The Navigation component only provides multiple back stack support in version 2.4.0 and higher. --> 2.3.5

You may wish to use a bottom app bar, an always-present or collapsible navigation drawer, a rail,

Safe Args, Safe Args Direction classes

setupBottomNavMenu, setupWithNavController val host: NavHostFragment = supportFragmentManager .findFragmentById(R.id.my_nav_host_fragment) as NavHostFragment? ?: return val navController = host.navController

AppBarConfiguration, setupActionBarWithNavController

LiveData: A data holder class that can be observed. notifies its observers

ViewModel communication between the Repository (data) and the UI. survive Activity/Fragment recreation. from Repository Flow to LiveData == asLiveData class WordViewModel(private val repository: WordRepository) : ViewModel() { val allWords: LiveData<List> = repository.allWords.asLiveData()}

Repository: class manage data sources. network--dao

Entity: Annotated class that describes a database table

Room database: Simplifies database

DAO: Data access object. A mapping of SQL queries to functions interface suspend function


Authentication Token (auth-token)

Your authenticating server: generate an auth-token, verify request

AccountManager: get request, new -- retrieve stored authtoken

AccountAuthenticator: call login activity, different services under a single account type.

AccountAuthenticatorActivity: Base class for the “sign-in/create account” activity: server->activity-> authenticator

var color: List<Color> = ArrayList(),
class CategoryViewHolder(val binding: ItemCategoryListBinding) : RecyclerView.ViewHolder(binding.root) {

class ProductViewModelFactory(private val productsRepository: ProductsRepository) : ViewModelProvider.Factory {

app_bar_category

These fragments can share a ViewModel using their activity scope to handle this communication

bottomsheet rounded button viewmodel communication

Shortcut

move line up : alt + up comment: ctrl + / block comment: ctrl + shift+ / format: ctrl alt L

Intent

  • manifest

  • main

Intent intent = getIntent(); String type = intent.getType(); String action = intent.getAction(); String input; if (action.equals(Intent.ACTION_SEND) && type != null) { if (type.equals("text/plain")) { input = intent.getStringExtra(Intent.EXTRA_TEXT); input = input.substring(input.indexOf("http")); Log.d(TAG, "onCreate: input=" + input); input = getRedirect(input);

        }
    }

check internet

private boolean checkInternetConnection() {

  ConnectivityManager connManager =
          (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);


  NetworkInfo networkInfo = connManager.getActiveNetworkInfo();

  if (networkInfo == null) {
      Toast.makeText(this, "No default network is currently active", Toast.LENGTH_LONG).show();
      return false;
  }

  if (!networkInfo.isConnected()) {
      Toast.makeText(this, "Network is not connected", Toast.LENGTH_LONG).show();
      return false;
  }

  if (!networkInfo.isAvailable()) {
      Toast.makeText(this, "Network not available", Toast.LENGTH_LONG).show();
      return false;
  }
  Toast.makeText(this, "Network OK", Toast.LENGTH_LONG).show();
  return true;

}

NetworkOnMainThreadException

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);

request text

public class IOUtils {

public static void closeQuietly(InputStream in)  {
    try {
        in.close();
    }catch (Exception e) {

    }
}

public static void closeQuietly(Reader reader)  {
    try {
        reader.close();
    }catch (Exception e) {

    }
}

}

protected String doInBackground(String... params) {
    String textUrl = params[0];

    InputStream in = null;
    BufferedReader br= null;
    try {
        URL url = new URL(textUrl);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();

        httpConn.setAllowUserInteraction(false);
        httpConn.setInstanceFollowRedirects(true);
        httpConn.setRequestMethod("GET");
        httpConn.connect();
        int tCode = httpConn.getResponseCode();

        if (resCode == HttpURLConnection.HTTP_OK) {
            in = httpConn.getInputStream();
            br= new BufferedReader(new InputStreamReader(in));

            StringBuilder sb= new StringBuilder();
            String s= null;
            while((s= br.readLine())!= null) {
                sb.append(s);
                sb.append("\n");
            }
            return sb.toString();
        } else {
            return null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        IOUtils.closeQuietly(in);
        IOUtils.closeQuietly(br);
    }
    return null;
}

request image

        if (resCode == HttpURLConnection.HTTP_OK) {
            in = httpConn.getInputStream();
        } else {
            return null;
        }

        Bitmap bitmap = BitmapFactory.decodeStream(in);

get redirect link

httpURLConnection.setInstanceFollowRedirects(false); httpURLConnection.connect(); link = httpURLConnection.getHeaderField("location");

httpURLConnection.setInstanceFollowRedirects(true); httpURLConnection.connect(); link = httpURLConnection.getURL().toString();

download image

  • permission: WRITE_EXTERNAL_STORAGE File file = new File(fileOutputPath); if (file.exists()){ Log.d(TAG, "doInBackground: image existed!!"); return null; } Bitmap bitmap = null; try { URL url = new URL(imageUrl); URLConnection conexion = url.openConnection(); conexion.connect(); int lenghtOfFile = conexion.getContentLength(); Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile); InputStream input = new BufferedInputStream(url.openStream()); OutputStream output = new FileOutputStream(fileOutputPath); byte data[] = new byte[1024]; long total = 0; int count; while ((count = input.read(data)) != -1) { total += count; output.write(data, 0, count); } Log.i(TAG, "doInBackground: image downloaded!"); output.flush(); output.close(); input.close();

      } catch (MalformedURLException | ProtocolException e) {
          Log.e(TAG, "doInBackground: ", e);
          e.printStackTrace();
      } catch (IOException e) {
          Log.e(TAG, "doInBackground: ", e);
          e.printStackTrace();
      }
    

asynctask progress bar

doinbackground() { this.publishProgress(progressInfo);

} @Override protected void onProgressUpdate(ProgressInfo... values) { // Progress ...values ProgressInfo progressInfo= values[0];

    int progress = progressInfo.getProgress();

    this.progressBar.setProgress(progress);
    this.textViewInfo.setText(progressInfo.getWorkingInfo());
}

Bitmap to file

Intent photoPickerIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); imgFile = new File("Cache directory","img.png"); //== where you want full size image photoPickerIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(imgFile)); startActivityForResult(photoPickerIntent, PickPhoto);

bm.compress(Bitmap.CompressFormat.PNG, 100, out);

write storage

public boolean isStoragePermissionGranted() {
    Log.i(TAG, "isStoragePermissionGranted: sdk=" + Build.VERSION.SDK_INT);
    if (Build.VERSION.SDK_INT >= 30) {
        if (!Environment.isExternalStorageManager()) {
            try {
                Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
                Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri);

// startActivityForResult(intent, 123); startActivity(intent);

            } catch (Exception ex) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);

// startActivityForResult(intent, 123); startActivity(intent); } } else { Log.v(TAG, "Permission is granted"); return true; } } else if (Build.VERSION.SDK_INT >= 23) { //use android:requestLegacyExternalStorage="true" for sdk29 if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { Log.v(TAG, "Permission is granted"); return true; } else { Log.v(TAG, "Permission is revoked"); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); return false; } } else { //permission is automatically granted on sdk<23 upon installation Log.v(TAG, "Permission is granted"); return true; } return true;

}

format string

String.format("/%s.webp",imageName);

change minCompileSDK 31

project structure --> SDK --> remove "Android API 30 31 32 Plattform" (only 29)

dialog

https://stackoverflow.com/questions/6276501/how-to-put-an-image-in-an-alertdialog-android https://stackoverflow.com/questions/17346102/must-every-activity-have-a-layout https://web.archive.org/web/20151116170752/https://code.google.com/p/android-developer-preview/issues/detail?id=2353

inflater

LayoutInflater inflater = getLayoutInflater(); View myLayout = inflater.inflate(R.layout.my_layout, mainLayout, false);

create linearLayout

    linearLayout = new LinearLayout(this);
    linearLayout.setOrientation(LinearLayout.VERTICAL);
    linearLayout.setLayoutParams(new LinearLayout.LayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)));

send intent

Intent sendIntent = new Intent(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/");

// (Optional) Here we're setting the title of the content sendIntent.putExtra(Intent.EXTRA_TITLE, "Introducing content previews");

// (Optional) Here we're passing a content URI to an image to be displayed sendIntent.setData(contentUri); sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Show the Sharesheet startActivity(Intent.createChooser(sendIntent, null));

Swip to refresh

protected void onCreate(Bundle savedInstanceState) { final SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh); pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refreshData(); // your code pullToRefresh.setRefreshing(false); } }); }

relaunch activity

add item to app bar

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.action_item_gear) {
        // Do something
        return true;
    }
    if (id == R.id.action_item_info) {
        // Do something
        return true;
    }
    return super.onOptionsItemSelected(item);
}

icons

File* → New → Image Assets → select launcher icon → choose image file.

pick dir

         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
            Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
            i.addCategory(Intent.CATEGORY_DEFAULT);
            startActivityForResult(Intent.createChooser(i, "Choose directory"), 9999);
        }

pick file

https://stackoverflow.com/questions/8945531/pick-any-kind-of-file-via-an-intent-in-android

Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("file/*"); startActivityForResult(intent, PICKFILE_REQUEST_CODE);

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode){
        case 9999:
            String uri = data.getData().getPath();
            String dir = uri.split(":")[1];
            textViewSelectPath.setText(DefaultValue.getRoot()+dir);
            MainActivity.savePath = DefaultValue.getRoot()+dir;
    }
}

radiobutton

int checkedRadioButtonId = radioGroupDiffLevel.getCheckedRadioButtonId(); this.radioGroupDiffLevel.check(checkedRadioButtonId);

SharedPreferences

SharedPreferences sharedPreferences= this.getSharedPreferences("gameSetting", Context.MODE_PRIVATE);

  • edit SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putInt("brightness", this.seekBarBrightness.getProgress()); editor.apply();

  • read if(sharedPreferences!= null) {

          int brightness = sharedPreferences.getInt("brightness", 90);
      }
    

default SharedPreferences

    String name =  context.getPackageName() + "_preferences";
    SharedPreferences sharedPreferences = context.getSharedPreferences(name, Context.MODE_PRIVATE );

intro splash

https://medium.com/geekculture/implementing-the-perfect-splash-screen-in-android-295de045a8dc#:~:text=A%20Splash%20Screen%20is%20a,you've%20just%20opened%20it.

getLaunchIntentForPackage, pinterest, getPackageManager, open activity

theme

android:theme="@style/Theme.PinTransparentTheme" == @theme.Theme.PinTransparentTheme

request write permission

  • https://www.tabnine.com/web/assistant/code/rs/5c7c0cee2f7dae000161c80a#L319

    private static final int REQUEST_COARSE_LOCATION = 141; private static final int REQUEST_WRITE_STORAGE = 142; private static final int SLIDE_POS_LOCATION_PERMISSION = 1;

    private void requestLocationPermission() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_COARSE_LOCATION); }

    private boolean haveStoragePermission() { int permissionState = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); return permissionState == PackageManager.PERMISSION_GRANTED; }

    private void requestStoragePermission() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE); }

    @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_COARSE_LOCATION: if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "User denied ACCESS_COARSE_LOCATION permission."); } else { Toast.makeText(this, R.string.permission_granted, Toast.LENGTH_SHORT).show(); Log.i(TAG, "User granted ACCESS_COARSE_LOCATION permission."); } break; case REQUEST_WRITE_STORAGE: if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "User denied WRITE_EXTERNAL_STORAGE permission."); } else { Toast.makeText(this, R.string.permission_granted, Toast.LENGTH_SHORT).show(); Log.i(TAG, "User granted WRITE_EXTERNAL_STORAGE permission."); } break; default: super.onRequestPermissionsResult(requestCode, permissions, grantResults); } }n

image full imageview, auto resize

android:adjustViewBounds="true"

Intent

  • manifest

  • main

Intent intent = getIntent(); String type = intent.getType(); String action = intent.getAction(); String input; if (action.equals(Intent.ACTION_SEND) && type != null) { if (type.equals("text/plain")) { input = intent.getStringExtra(Intent.EXTRA_TEXT); input = input.substring(input.indexOf("http")); Log.d(TAG, "onCreate: input=" + input); input = getRedirect(input);

        }
    }

back button, action bar

ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); }

  • onOptionsItemSelected
    case android.R.id.home: this.finish(); return true;

action bar label

push notification

c2dm: cloud to device message

intent open folder

ntent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("file/*"); startActivityForResult(intent, YOUR_RESULT_CODE);

  • open a specific folder:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

intent.setDataAndType(Uri.parse(Environment.getExternalStorageDirectory().getPath()

  • File.separator + "myFolder" + File.separator), "file/*"); startActivityForResult(intent, YOUR_RESULT_CODE);

size convert

 public static String formatFileSize(long size) {
    String hrSize = null;

    double b = size;
    double k = size/1024.0;
    double m = ((size/1024.0)/1024.0);
    double g = (((size/1024.0)/1024.0)/1024.0);
    double t = ((((size/1024.0)/1024.0)/1024.0)/1024.0);

    DecimalFormat dec = new DecimalFormat("0.00");

    if ( t>1 ) {
        hrSize = dec.format(t).concat(" TB");
    } else if ( g>1 ) {
        hrSize = dec.format(g).concat(" GB");
    } else if ( m>1 ) {
        hrSize = dec.format(m).concat(" MB");
    } else if ( k>1 ) {
        hrSize = dec.format(k).concat(" KB");
    } else {
        hrSize = dec.format(b).concat(" B");
    }

    return hrSize;
}

textview

android:selectAllOnFocus="true"

Theme

work android:theme="@style/Theme.MaterialComponents.BottomSheetDialog"

not work!! android:theme="@style/ThemeOverlay.MaterialComponents.BottomSheetDialog"

scale type

https://thoughtbot.com/blog/android-imageview-scaletype-a-visual-guide android:layout_width="300dp" android:layout_height="300dp" android:adjustViewBounds="true" android:scaleType="centerCrop" android:layout_margin="5dp"/>

view dir

Intent contact

public void pickContactHandler( ) {
    Intent contactPickerIntent = new Intent(Intent.ACTION_PICK,
            ContactsContract.Contacts.CONTENT_URI);
    startActivityForResult(contactPickerIntent, CONTACT_PICKER_RESULT);
}

https://o7planning.org/12649/android-quickcontactbadge

read content uri

            Uri uri = data.getData();
            Log.d(TAG, "onActivityResult: uri=" + uri.getPath());
            try {
                InputStream inputStream = getContentResolver().openInputStream(uri);
                BufferedReader br= new BufferedReader(new InputStreamReader(inputStream));

                StringBuilder sb= new StringBuilder();
                String s= null;
                while((s= br.readLine())!= null) {
                    sb.append(s);
                    sb.append("\n");
                }
                Log.d(TAG, "onActivityResult: res="+ sb.toString());

scrollView

protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putIntArray("ARTICLE_SCROLL_POSITION", new int[]{ mScrollView.getScrollX(), mScrollView.getScrollY()}); }

protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); final int[] position = savedInstanceState.getIntArray("ARTICLE_SCROLL_POSITION"); if(position != null) mScrollView.post(new Runnable() { public void run() { mScrollView.scrollTo(position[0], position[1]); } }); }

scrollView

align center

linearLayout

relativeLayout

android:layout_centerVertical="true" android:layout_alignParentBottom="true" android:layout_above="@+id/navigation" android:layout_centerInParent="true"

color from string

// holder.itemImage.setBackgroundColor(Color.parseColor(product.getColor()));

set shape color

Drawable background = imageView.getBackground();

if (background instanceof ShapeDrawable) { // cast to 'ShapeDrawable' ShapeDrawable shapeDrawable = (ShapeDrawable) background; shapeDrawable.getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet)); } else if (background instanceof GradientDrawable) { // cast to 'GradientDrawable' GradientDrawable gradientDrawable = (GradientDrawable) background; gradientDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet)); } else if (background instanceof ColorDrawable) { // alpha value may need to be set again after this call ColorDrawable colorDrawable = (ColorDrawable) background; colorDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet)); }

load raw resource file

  • https://stackoverflow.com/questions/6349759/using-json-file-in-android-app-resources

    private String loadJSONFromAsset() { String json = null; try { InputStream is = mainActivity.getResources().openRawResource(R.raw.shoes);; int size = is.available(); byte[] buffer = new byte[size]; is.read(buffer); is.close(); json = new String(buffer, "UTF-8");

      } catch (IOException ex) {
          ex.printStackTrace();
          return null;
      }
      return json;
    

    }

circle drawable

colorprimary

  • https://stackoverflow.com/questions/45879513/what-is-the-difference-between-colorprimary-and-colorprimarydark-in-themes colorPrimary – The color of the app bar. colorPrimaryDark – The color of the status bar and contextual app bars; this is normally a dark version of colorPrimary. colorAccent – The color of UI controls such as check boxes, radio buttons, and edit text boxes. windowBackground – The color of the screen background. textColorPrimary – The color of UI text in the app bar. statusBarColor – The color of the status bar. navigationBarColor – The color of the navigation bar.

String format

pojo, read json

String file = "raw/test.txt"; // res/raw/test.txt also work. InputStream in = this.getClass().getClassLoader().getResourceAsStream(file);

get bitmap from uri

Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);

recyclerview

GridLayoutManager gridLayoutManager = new GridLayoutMananger(context, spancount, LinearLayoutManger.vertical, reverselayout=false)

rcvView.setLayoutManger(gridLayoutManager) rcvView.setAdapter(adapter) rcvView.setFocusable(false)

gravity

android:gravity handles the alignment of its children, android:layout_gravity handles the alignment of itself.

navigation label fragment

https://stackoverflow.com/questions/60464351/why-is-navigation-component-fragment-label-not-working

navigation in fragment

private fun navigateToPlantListPage() {
    requireActivity().findViewById<ViewPager2>(R.id.view_pager).currentItem =
        PLANT_LIST_PAGE_INDEX
}

navigation by appbar (not by navhost)

binding.favTopAppBar.topAppBar.setNavigationOnClickListener { findNavController().navigateUp() }

default preference

PreferenceManager.getDefaultSharedPreferences(context)

submitdata postdelay handler

private val mMainHandler = Handler(Looper.getMainLooper())

    mMainHandler.removeCallbacksAndMessages(null)
    mMainHandler.postDelayed({
        adapter.clear() // todo gently change data
        adapter.addAll(list)
        adapter.notifyDataSetChanged()
        Log.d(TAG, "setAppBarMenu: start filter count=${adapter.count}")

    }, 500)

Cannot create an instance of class com.goldenowl.ecommerce.viewmodels.AuthViewModel

[wrong] class AuthViewModel(application: MyApplication) [true ] class AuthViewModel(application: Application)

hide keyboard

fun Activity.hideKeyboard() { hideKeyboard(currentFocus ?: View(this)) }

fun Context.hideKeyboard(view: View) { val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0) }

pick image

    val callback = ActivityResultCallback<ActivityResult> { result ->
        if (result.resultCode != Activity.RESULT_OK)
        val data: Intent = result.data ?: return@ActivityResultCallback
        val file: Uri? = data.data
       }

    imageActivityResultLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult(), callback)
}

    val intent = Intent(Intent.ACTION_PICK)
    intent.type = "image/*"
    if (requireActivity().packageManager.resolveActivity(intent, 0) != null) {
        imageActivityResultLauncher.launch(intent)
    } else {
        Toast.makeText(activity, getString(R.string.no_image_picker), Toast.LENGTH_SHORT).show()
    }

nestedscrollview

fillViewPort =true

appbar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment