/* * Copyright 2017 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.example.playgamesshadows import android.app.LoaderManager import android.content.AsyncTaskLoader import android.content.Context import android.content.Intent import android.content.Loader import android.graphics.drawable.Drawable import android.os.Bundle import android.support.v7.app.AppCompatActivity import android.support.v7.widget.LinearSnapHelper import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) carousel.setHasFixedSize(true) LinearSnapHelper().attachToRecyclerView(carousel) carousel.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { val center = recyclerView.width / 2 (0 until recyclerView.childCount).forEach { i -> val child = recyclerView.getChildAt(i) as? IconView ?: return@forEach val cx = (child.left + child.right) / 2 val offsetPx = Math.abs(center - cx) child.offset = offsetPx / center.toFloat() } } }) loaderManager.initLoader(0, Bundle.EMPTY, object : LoaderManager.LoaderCallbacks> { override fun onCreateLoader(id: Int, args: Bundle?) = AppIconLoader(applicationContext) override fun onLoadFinished(loader: Loader>, icons: List) { loading.visibility = View.GONE carousel.adapter = AppAdapter(icons) } override fun onLoaderReset(loader: Loader>?) {} }) } private class AppIconLoader(context: Context) : AsyncTaskLoader>(context) { private val icons = mutableListOf() override fun onStartLoading() { if (icons.isNotEmpty()) { deliverResult(icons) } else { forceLoad() } } override fun loadInBackground(): List? { val pm = context.packageManager val launchableAppIcons = mutableListOf() val launcherIntent = Intent().apply { addCategory(Intent.CATEGORY_LAUNCHER) } pm.getInstalledApplications(0).forEach { appInfo -> launcherIntent.`package` = appInfo.packageName // only show launch-able apps if (pm.queryIntentActivities(launcherIntent, 0).isNotEmpty()) { launchableAppIcons += appInfo.loadUnbadgedIcon(pm) } } return launchableAppIcons } override fun deliverResult(data: List) { icons += data super.deliverResult(data) } } class AppAdapter(private val icons: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { return AppViewHolder(LayoutInflater.from(parent.context) .inflate(R.layout.app_item, parent, false) as IconView) } override fun onBindViewHolder(holder: AppViewHolder, position: Int) { holder.iconView.icon = icons[position] } override fun getItemCount() = icons.size } class AppViewHolder(val iconView: IconView) : RecyclerView.ViewHolder(iconView) }