尝试用kotlin做一个app(第一天)

纵饮孤独 提交于 2020-02-21 08:14:11

1.先添加一下anko

依赖:implementation "org.jetbrains.anko:anko:$anko_version"

版本:ext.anko_version='0.10.8'

2.新建Activity和Fragment的两个基类,方便以后使用

abstract class BaseActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(getLayoutId())
        initData();
        onListener();
    }

    abstract fun getLayoutId(): Int;//继承此类必须先实现此方法

    protected open fun initData(){

    }

    protected open fun onListener() {

    }

//

abstract class BaseFragment:Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initData()
    }
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return initView();
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        onListener()
    }

    abstract fun initView():View?

    protected open fun initData(){

    }

    protected open fun onListener(){

    }
}
3.底部导航
方案一:bottombar
依赖:implementation 'com.roughike:bottom-bar:2.3.1'
activity_main.xml改成LinearLayout布局,设置垂直布局
<FrameLayout
        android:id="@+id/contentContainer"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"/>


    <com.roughike.bottombar.BottomBar
        android:id="@+id/bottomBar"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        app:bb_tabXmlResource="@xml/bottombar_tabs"/>

 

新建xml Directory,添加bottombar_tabs.xml
<?xml version="1.0" encoding="utf-8"?>
<tabs>
    <tab
        id="@+id/tab_homepage"
        icon="@drawable/homepage_icon"
        title="主页" />
    <tab
        id="@+id/tab_favorites"
        icon="@drawable/favorites_icon"
        title="收藏" />
    <tab
        id="@+id/tab_message"
        icon="@drawable/message_icon"
        title="消息" />
    <tab
        id="@+id/tab_personal"
        icon="@drawable/personal_icon"
        title="我的" />
</tabs>

 

添加图标资源到drawable-xxhdpi目录中(不能直接添加到drawable中)
添加监听很简单
    override fun initData() {
        bottomBar.setOnTabSelectListener{
            //it即是tab的id
//            println(it)
        }

 

接下来准备点击切换的四个fragment,都继承自BaseFragment,例如
class FavoritesFragment:BaseFragment() {

    override fun initView(): View? {
        var textView:TextView=TextView(activity) //getActivity()返回与之关联的activity
        textView.text="收藏"
        return textView
    }
}

 

再准备一个管理fragment的类FragmentManage
class FragmentManage {
        fun getFragment(tab_id:Int):BaseFragment?{
            when(tab_id){
                R.id.tab_homepage->return HomePageFragment()
                R.id.tab_favorites->return FavoritesFragment()
                R.id.tab_message->return MessageFragment()
                R.id.tab_personal->return Personal()
            }
            return null
        }
}

 

优化后的代码,创建单例模式,采用懒加载定义变量
class FragmentManage private constructor(){
    val homePageFragmeng by lazy{HomePageFragment()}
    val favoritesFragment by lazy{FavoritesFragment()}
    val messageFragment by lazy{MessageFragment()}
    val PersonalFragment by lazy{Personal()}

    companion object{
        val fragmentManage by lazy{
            FragmentManage()
        }
    }
        fun getFragment(tab_id:Int):BaseFragment?{
            when(tab_id){
                R.id.tab_homepage->return homePageFragmeng
                R.id.tab_favorites->return favoritesFragment
                R.id.tab_message->return messageFragment
                R.id.tab_personal->return PersonalFragment
            }
            return null
        }
}

 

这里可能找不到id,重启一下就可以了。R资源路径app\build\generated\not_namespaced_r_class_sources\debug\r\com\vocus\justtest
在MainActivity中设置对bottomBar的监听,并动态添加fragment
override fun initData() {
        bottomBar.setOnTabSelectListener {
            //it即是tab的id
//            println(it)
            val transAction = supportFragmentManager.beginTransaction()
            //transAction.replace(R.id.contentContainer,FragmentManage().getFragment(it) as BaseFragment, it.toString())
            transAction.replace(R.id.contentContainer,FragmentManage.fragmentManage.getFragment(it)!!,it.toString())
            transAction.commit()

        }
    }
 
效果:
 

 

 

 方案二:BottomNavigationView
null
4.主界面,设置HomePageFragment
设置状态栏背景透明
null
广告图片轮播(ViewPager)
设置homepagefragment布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp_homePageAd"
        android:layout_width="match_parent"
        android:layout_height="300dp">
    </androidx.viewpager.widget.ViewPager>

    <LinearLayout
        android:id="@+id/dot_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_centerHorizontal="true"
        android:layout_alignBottom="@+id/vp_homePageAd"
        android:layout_marginBottom="10dp">

    </LinearLayout>

</RelativeLayout>

 

新建HomePageAdAdapter类
class HomePageAdAdapter(): PagerAdapter(){
    private val imageViewList=ArrayList<ImageView>()
    constructor(imageViewList:ArrayList<ImageView>):this(){
        this.imageViewList.addAll(imageViewList)
    }

    override fun isViewFromObject(view: View, `object`: Any): Boolean {
        return view==`object`
    }

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
//        var textView= TextView(container.context)
//        textView.text="test"
//        container.addView(textView)
//        return textView
        container.addView(imageViewList.get(position))
        return imageViewList.get(position)
    }

    override fun getCount(): Int {
        return imageViewList.size
    }

    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
        container.removeView(`object` as View)
    }
}

 

在HomePageFragment中添加代码
  • 重写onListener方法(在onActivityCreated的声明周期里)
  • 定义资源
/定义图片资源,一共五张
 var imagesId=listOf(R.drawable.pic1,R.drawable.pic2,R.drawable.pic3,R.drawable.pic4,R.drawable.pic5)

        //定义五个图片控件,用于加载图片资源
        var imageViewList=ArrayList<ImageView>()
        for(i in 0 until 5){
            var imageView:ImageView=ImageView(activity)
            imageView.setImageResource(imagesId[i])
            imageViewList.add(imageView)

        }
 
  • 添加监听
//        var vp_homePage:ViewPager=view!!.findViewById(R.id.vp_homePageAd)
//        vp_homePage.adapter=HomePageAdAdapter()
        vp_homePageAd.adapter=HomePageAdAdapter(imageViewList)

        //

        //添加页面改变监听
        vp_homePageAd.addOnPageChangeListener(object :ViewPager.OnPageChangeListener{
            override fun onPageScrollStateChanged(state: Int) {

            }

            //页面滚动的时候
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {

            }

            override fun onPageSelected(position: Int) {
                //添加圆点导航
                addDots(position)
            }

        })

    }

 

  • 增加圆点导航方法
//偷懒的方法
fun addDots(position:Int){

        dot_container.removeAllViews()
        var dots=arrayOf<TextView>(TextView(activity),TextView(activity),TextView(activity),TextView(activity),TextView(activity))
       dots.forEach {
           it.text="."
           it.setTextColor(Color.GRAY)
           it.textSize=30f
       }

        for(i in 0 until 5) {
            dot_container.addView(dots[i])
        }
        dots[position].setTextColor(Color.WHITE)

    }

 

The specified child already has a parent. You must call removeView() on the child's parent first
我在把同一个TextView多次添加到布局中发生此错误,因为添加一次之后TextView就有parent了,直接在for循环中使用(textView.parent as ViewGroup?)!!.removeView(textView)也不行,因为循环的第二次会把第一次添加的移除。所以只能创建多个textview
错误代码为:
fun addDots(position:Int){
        var dots=ArrayList<TextView>()
        var textView=TextView(context)
        textView.text="."
        textView.setTextColor(Color.RED)
        textView.textSize=30f

        for(i in 0 until 5) {
            if ((textView.parent as ViewGroup?) != null) {
                (textView.parent as ViewGroup?)!!.removeView(textView)
            }
            dot_container.addView(textView)
        }
    }

 

继续完善

  • 增加无限翻页
将getCount()返回值设置为Integer.MAX_VALUE,资源列表用到position取值的地方,要按5取模position%5,这样可以实现向后无限翻页;为了保证向前也能无限翻页,将PagerView的当前页设置为Integer.MAX_VALUE/2,同时-Integer.MAX_VALUE/2%5保证为5的倍数
vp_homePageAd.currentItem=Integer.MAX_VALUE/2-Integer.MAX_VALUE/2%5
  • 循环播放
val handler: Handler =object:Handler(){
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            vp_homePageAd.currentItem+=1

            sendEmptyMessageDelayed(0,4000)
        }

    }

 

调用:handler.sendEmptyMessageDelayed(0,4000)
  • 添加点击事件参考
vp_homePageAd.setOnTouchListener(object:View.OnTouchListener{
            override fun onTouch(p0: View?, p1: MotionEvent?): Boolean {
                //Toast.makeText(context,"-x:${p1.x},y:${p1.y}",Toast.LENGTH_SHORT).show();
                var flag:Int=0
                when(p1!!.action){
                    MotionEvent.ACTION_DOWN->flag=0
                    //MotionEvent.ACTION_UP->flag=1
                    MotionEvent.ACTION_MOVE->flag=2
                }
                println(flag.toString())
                if(p1!!.action==MotionEvent.ACTION_UP&& flag==0){
                    val currentPage=vp_homePageAd.currentItem%5
                    when(currentPage+1){
                        1->Toast.makeText(context,"1",Toast.LENGTH_SHORT).show()
                        2->Toast.makeText(context,"2",Toast.LENGTH_SHORT).show()
                        3->Toast.makeText(context,"3",Toast.LENGTH_SHORT).show()
                        4->Toast.makeText(context,"4",Toast.LENGTH_SHORT).show()
                        5->Toast.makeText(context,"5",Toast.LENGTH_SHORT).show()

                    }
                }
                return false
            }

        })

(这个有问题。。。)

  •  其他
·第一次进去程序没有圆点导航,需要初始化一下
·可以给每个页面添加文字说明
·用户按住某个页面时,应该停止轮播
 效果

源码:

链接:https://pan.baidu.com/s/1NOoX2E7tV9js9QuNr-i5Hw
提取码:fwva

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!