使用kotlin编写第一个Android应用界面

来源:互联网 发布:隔壁老王出处 知乎 编辑:程序博客网 时间:2024/05/23 13:21

使用Kotlin开发App快速高效,最直接的一个感受就是你的代码量减少了很多。这里写了一个小例,效果如下:

这里写图片描述

这个界面总体布局是:根布局是CoordinatorLayout,然后上部分是AppBarLayout,下部是ViewPager管理的Fragment。下面直接上代码,根据代码说明相关情况。

  • CoordinatorActivity.kt文件
import kotlinx.android.synthetic.main.activity_coordinator.*class CoordinatorActivity : FragmentActivity() {    private lateinit var mFragments: MutableList<Fragment>    private var mTitles = arrayOf("主页", "微博", "相册")    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_coordinator)        setupViewPager()    }    private fun setupViewPager() {        mFragments = ArrayList<Fragment>()//        for (i in mTitles.indices) {//            val listFragment = ListFragment.newInstance(mTitles[i])//            mFragments.add(listFragment)//        }        mTitles.map {            val listFragment = ListFragment.newInstance(it)            mFragments.add(listFragment)        }        // 为ViewPager设置适配器        val adapter = ContentPagerAdapter(mFragments, mTitles)        viewpager.adapter = adapter        //  第三步:将ViewPager与TableLayout 绑定在一起        tabLayout.setupWithViewPager(viewpager)    }    internal inner class ContentPagerAdapter(val tabFragments: List<Fragment>, val tabIndicators: Array<String>)        : FragmentPagerAdapter(supportFragmentManager) {        override fun getItem(position: Int): Fragment {            return tabFragments[position]        }        override fun getCount(): Int {            return tabIndicators.size        }        override fun getPageTitle(position: Int): CharSequence {            return tabIndicators[position]        }    }}

一般贴代码我会省略导入文件,这里我特意贴出一条import信息,这是kotlin对android的一个功能扩展。使得我们不用再去写那么多findViewById了。

  • ListFragment.kt文件
import kotlinx.android.synthetic.main.fragment_list.*class ListFragment(override val layoutId: Int) : BaseFragment() {    private var mRecyclerView: RecyclerView? = null    private var title:String? = "测试"    private var mDatas: MutableList<String> = ArrayList()    private var mAdapter: MyAdapter? = null//    private var mSwipeRefreshLayout: SwipeRefreshLayout? = null    override fun initView(view: View?) {    }    //这里使用kotlin-android-extensions, 防止view为空,所以放在onViewCreated方法中    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        val arguments = arguments //property access syntax        title = arguments?.getString(KEY)        val layoutManager = LinearLayoutManager(mContext)        recyclerView!!.layoutManager = layoutManager        (0..49).map {            var s = String.format("我是第%d个" + title, it)            mDatas.add(s)        }//        for (i in 0..49) {//            val s = String.format("我是第%d个" + title, i)//            mDatas.add(s)//        }        mAdapter = MyAdapter(mContext, mDatas)        recyclerView!!.adapter = mAdapter        swipeRefreshLayout!!.setOnRefreshListener {            swipeRefreshLayout!!.postDelayed({                swipeRefreshLayout!!.isRefreshing = false                Toast.makeText(mContext, "刷新完成", Toast.LENGTH_SHORT).show()            }, 1200)        }    }    fun tooglePager(isOpen: Boolean) {        if (isOpen) {            setRefreshEnable(false)            scrollToFirst(false)        } else {            setRefreshEnable(true)        }    }    fun scrollToFirst(isSmooth: Boolean) {        if (isSmooth) {            mRecyclerView?.smoothScrollToPosition(0)        } else {            mRecyclerView?.scrollToPosition(0)        }    }    fun setRefreshEnable(enabled: Boolean) {        swipeRefreshLayout!!.isEnabled = enabled    }//    override fun getLayoutId(): Int {//        return R.layout.fragment_list//    }    override fun fetchData() {    }    companion object {        private val KEY = "key"        fun newInstance(title: String): ListFragment {            val fragment = ListFragment(R.layout.fragment_list)            val bundle = Bundle()            bundle.putString(KEY, title)            fragment.arguments = bundle            return fragment        }    }}

Fragment中我们也可以使用Kotlin针对Android的扩展功能,但是我们要获取布局文件中的View时不能在onCreateView方法中来获取,否则会抛出异常,因为在这个方法中获取不到,需要在onViewCreated方法中执行相关操作。

  • BaseFragment.kt文件
abstract class BaseFragment : Fragment() {    protected var mView: View? = null    /**     * 表示View是否被初始化     */    protected var isViewInitiated: Boolean = false    /**     * 表示对用户是否可见     */    protected var isVisibleToUser: Boolean = false    /**     * 表示数据是否初始化     */    protected var isDataInitiated: Boolean = false    protected lateinit var mContext: Context    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)    }    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {        if (mView == null) {            mContext = context            mView = View.inflate(mContext, layoutId, null)            initView(mView)        } else {            // 缓存的rootView需要判断是否已经被加过parent,如果有parent需要从parent删除,            // 要不然会发生这个rootview已经有parent的错误。            //Note that despite the fact that the right-hand side of as? is a non-null type String the result of the cast is nullable.            val parent = mView?.parent as ViewGroup?            parent?.removeView(mView)        }        return mView    }    protected abstract open fun initView(view: View?)    protected abstract val layoutId: Int    override fun onActivityCreated(savedInstanceState: Bundle?) {        super.onActivityCreated(savedInstanceState)        isViewInitiated = true        initListener()        initData()        prepareFetchData()    }    protected fun initListener() {}    override fun setUserVisibleHint(isVisibleToUser: Boolean) {        super.setUserVisibleHint(isVisibleToUser)        this.isVisibleToUser = isVisibleToUser        prepareFetchData()    }    abstract fun fetchData()    /***     * @param forceUpdate 表示是否在界面可见的时候是否强制刷新数据     * *       * @return     */    @JvmOverloads fun prepareFetchData(forceUpdate: Boolean = false): Boolean {        if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {            //  界面可见的时候再去加载数据            fetchData()            isDataInitiated = true            return true        }        return false    }    override fun onDestroyView() {        super.onDestroyView()    }    protected fun initData() {}}

@JvmOverloads是对应有默认参数的情况,相对Java会生成多个重载方法。

  • MyAdapter.kt文件
class MyAdapter(private val context: Context, private val datas: List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {        val view = View.inflate(context, R.layout.data_recycler, null)        return MyViewHolder(view)    }    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {        holder.setIsRecyclable(false) // itemView是否重用        holder.item.text = datas[position]    }    override fun getItemCount(): Int {        return datas.size    }    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {        var item: TextView = itemView.findViewById(R.id.tv_item) as TextView    }}

至此,这个界面效果就完成了。如果你用Java实现一遍的话,再对比一下代码量会发现kotlin简洁很多。

项目Github地址,仅供参考学习。

原创粉丝点击