美文网首页
完整app -- Eyepetizer 学习

完整app -- Eyepetizer 学习

作者: 客观开发者 | 来源:发表于2021-04-20 14:35 被阅读0次

    最近看的一个Eyepetizer 的项目挺好的。学习如下
    源码地址:https://www.jianshu.com/p/bb1b45eebecc

    1,自定义 字体

      class TypefaceTextView : AppCompatTextView {
    
    constructor(context: Context) : this(context, null)
    
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        attrs?.let {
            val typedArray = context.obtainStyledAttributes(it, R.styleable.TypefaceTextView, 0, 0)
            val typefaceType = typedArray.getInt(R.styleable.TypefaceTextView_typeface, 0)
            typeface = getTypeface(typefaceType)
            typedArray.recycle()
        }
    }
    
    companion object {
    
        /**
         * 根据字体类型,获取自定义字体。
         */
        fun getTypeface(typefaceType: Int?) = when (typefaceType) {
            TypeFaceUtil.FZLL_TYPEFACE -> TypeFaceUtil.getFzlLTypeface()
            TypeFaceUtil.FZDB1_TYPEFACE -> TypeFaceUtil.getFzdb1Typeface()
            TypeFaceUtil.FUTURA_TYPEFACE -> TypeFaceUtil.getFuturaTypeface()
            TypeFaceUtil.DIN_TYPEFACE -> TypeFaceUtil.getDinTypeface()
            TypeFaceUtil.LOBSTER_TYPEFACE -> TypeFaceUtil.getLobsterTypeface()
            else -> Typeface.DEFAULT
        }
    }
    

    }
    TypeFaceUtil 内容

    const val FZLL_TYPEFACE = 1
    
    const val FZDB1_TYPEFACE = 2
    
    const val FUTURA_TYPEFACE = 3
    
    const val DIN_TYPEFACE = 4
    
    const val LOBSTER_TYPEFACE = 5
    
    private var fzlLTypeface: Typeface? = null
    
    private var fzdb1Typeface: Typeface? = null
    
    private var futuraTypeface: Typeface? = null
    
    private var dinTypeface: Typeface? = null
    
    private var lobsterTypeface: Typeface? = null
    
    fun getFzlLTypeface() = if (fzlLTypeface == null) {
        try {
            Typeface.createFromAsset(EyepetizerApplication.context.assets, "fonts/FZLanTingHeiS-L-GB-Regular.TTF")
        } catch (e: RuntimeException) {
            Typeface.DEFAULT
        }
    } else {
        fzlLTypeface!!
    }
    
    fun getFzdb1Typeface() = if (fzdb1Typeface == null) {
        try {
            Typeface.createFromAsset(EyepetizerApplication.context.assets, "fonts/FZLanTingHeiS-DB1-GB-Regular.TTF")
        } catch (e: RuntimeException) {
            Typeface.DEFAULT
        }
    } else {
        fzdb1Typeface!!
    }
    
    fun getFuturaTypeface() = if (futuraTypeface == null) {
        try {
            Typeface.createFromAsset(EyepetizerApplication.context.assets, "fonts/Futura-CondensedMedium.ttf")
        } catch (e: RuntimeException) {
            Typeface.DEFAULT
        }
    } else {
        futuraTypeface!!
    }
    
    fun getDinTypeface() = if (dinTypeface == null) {
        try {
            Typeface.createFromAsset(EyepetizerApplication.context.assets, "fonts/DIN-Condensed-Bold.ttf")
        } catch (e: RuntimeException) {
            Typeface.DEFAULT
        }
    
    } else {
        dinTypeface!!
    }
    
    fun getLobsterTypeface() = if (lobsterTypeface == null) {
        try {
            Typeface.createFromAsset(EyepetizerApplication.context.assets, "fonts/Lobster-1.4.otf")
        } catch (e: RuntimeException) {
            Typeface.DEFAULT
        }
    
    } else {
        lobsterTypeface!!
    }
    
       <declare-styleable name="TypefaceTextView">
            <attr name="typeface">
                <enum name="fzlLTypeface" value="1" />
                <enum name="fzdb1Typeface" value="2" />
                <enum name="futuraTypeface" value="3" />
                <enum name="dinTypeface" value="4" />
                <enum name="lobsterTypeface" value="5" />
            </attr>
        </declare-styleable>
    
    fonts/fonts 放入字体
    

    使用

     <com.eyepetizer.android.ui.common.view.TypefaceTextView
                android:id="@+id/tvTitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/ivAvatar"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="18dp"
                android:layout_marginBottom="50dp"
                android:text="@string/guide_login_tips_four"
                android:textColor="@color/grayDark"
                android:textSize="12sp"
                app:typeface="fzlLTypeface" />
    

    2,颜色 收集

        <color name="white">#ffffff</color>
        <color name="whiteAlpha85">#26ffffff</color>
        <color name="whiteAlpha80">#33ffffff</color>
        <color name="whiteAlpha60">#66ffffff</color>
        <color name="whiteAlpha50">#80ffffff</color>
        <color name="whiteAlpha35">#a6ffffff</color>
        <color name="whiteAlpha25">#bfffffff</color>
        <color name="whiteAlpha20">#ccffffff</color>
        <color name="whiteAlpha10">#e6ffffff</color>
        <color name="blackAlpha95">#0d000000</color>
        <color name="blackAlpha85">#26000000</color>
        <color name="blackAlpha80">#33000000</color>
        <color name="blackAlpha70">#4d000000</color>
        <color name="blackAlpha60">#66000000</color>
        <color name="blackAlpha55">#73000000</color>
        <color name="blackAlpha50">#80000000</color>
        <color name="blackAlpha45">#8c000000</color>
        <color name="blackAlpha20">#cc000000</color>
        <color name="black">#000000</color>
    
    1. 友盟统计的使用

    下载
    https://developer.umeng.com/sdk/android
    UMConfigure.init(this, null, null, UMConfigure.DEVICE_TYPE_PHONE, null)
    UMConfigure.setLogEnabled(BuildConfig.DEBUG)
    <meta-data
    android:name="UMENG_APPKEY"
    android:value="5ee21dfcdbc2ec078743b1f3" />
    <meta-data
    android:name="UMENG_CHANNEL"
    android:value="opensource" />

    4,de8错误使用
    MultiDex.install(this)

    5,leakcanary 的使用
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4'

    使用

    6.PermissionX 权限的使用
    implementation 'com.android.support:multidex:1.0.3'
    主要好是内置了dialog 取消和 同意

    
        private fun requestWriteExternalStoragePermission() {
            PermissionX.init(this@SplashActivity).permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .onExplainRequestReason { scope, deniedList ->
                    val message = GlobalUtil.getString(R.string.request_permission_picture_processing)
                    scope.showRequestReasonDialog(deniedList, message, GlobalUtil.getString(R.string.ok), GlobalUtil.getString(R.string.cancel))
                }
                .onForwardToSettings { scope, deniedList ->
                    val message = GlobalUtil.getString(R.string.request_permission_picture_processing)
                    scope.showForwardToSettingsDialog(deniedList, message, GlobalUtil.getString(R.string.settings), GlobalUtil.getString(R.string.cancel))
                }
                .request { allGranted, grantedList, deniedList ->
                    requestReadPhoneStatePermission()
                }
        }
    
        private fun requestReadPhoneStatePermission() {
            PermissionX.init(this@SplashActivity).permissions(Manifest.permission.READ_PHONE_STATE)
                .onExplainRequestReason { scope, deniedList ->
                    val message = GlobalUtil.getString(R.string.request_permission_access_phone_info)
                    scope.showRequestReasonDialog(deniedList, message, GlobalUtil.getString(R.string.ok), GlobalUtil.getString(R.string.cancel))
                }
                .onForwardToSettings { scope, deniedList ->
                    val message = GlobalUtil.getString(R.string.request_permission_access_phone_info)
                    scope.showForwardToSettingsDialog(deniedList, message, GlobalUtil.getString(R.string.settings), GlobalUtil.getString(R.string.cancel))
                }
                .request { allGranted, grantedList, deniedList ->
                    setContentView(R.layout.activity_splash)
                }
        }
    

    7.refresh 下拉刷新和上拉更多的使用
    implementation 'com.scwang.smart:refresh-header-material:2.0.0'
    implementation 'com.scwang.smart:refresh-layout-kernel:2.0.0'

    最新版本更新。额尽量使用最新的。好像包名都修改了。

    在application 中配置

     init {
            SmartRefreshLayout.setDefaultRefreshInitializer { context, layout ->
                layout.setEnableLoadMore(true)
                layout.setEnableLoadMoreWhenContentNotFull(true)
            }
    
            SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout ->
                layout.setEnableHeaderTranslationContent(true)
                MaterialHeader(context).setColorSchemeResources(R.color.blue, R.color.blue, R.color.blue)
            }
    
            SmartRefreshLayout.setDefaultRefreshFooterCreator { context, layout ->
                layout.setEnableFooterFollowWhenNoMoreData(true)
                layout.setEnableFooterTranslationContent(true)
                layout.setFooterHeight(153f)
                layout.setFooterTriggerRate(0.6f)
                NoStatusFooter.REFRESH_FOOTER_NOTHING = "- The End -"
                NoStatusFooter(context).apply {
                    setAccentColorId(R.color.colorTextPrimary)
                    setTextTitleSize(16f)
                }
            }
        }
    

    java 中使用 请用static{}

    1. kotlin 携程的使用
        private val job by lazy { Job() }
    GlobalScope.launch(Dispatchers.Main) {}
    //替换下面
     CoroutineScope(job).launch {
                delay(splashDuration)
                MainActivity.start(this@SplashActivity)
                finish()
            }
     
      override fun onDestroy() {
            super.onDestroy()
            job.cancel()
        }
    

    携程里面好多,可以搜索一下。

    9.动画的使用。。原来也可以用lazy 来做。

        private val alphaAnimation by lazy {
            AlphaAnimation(0.5f, 1.0f).apply {
                duration = splashDuration
                fillAfter = true
            }
        }
    
        private val scaleAnimation by lazy {
            ScaleAnimation(1f, 1.05f, 1f, 1.05f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f).apply {
                duration = splashDuration
                fillAfter = true
            }
        }
    
    

    10 constraintlayout 里面的方法的使用。。
    主要是里面就几个方法,居然自己还不好用。。。

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="42dp"
        android:background="@color/colorPrimary"
        android:paddingLeft="24dp"
        android:paddingRight="24dp">
    
        <ImageView
            android:id="@+id/ivHomePage"
            android:layout_width="23dp"
            android:layout_height="23dp"
            android:src="@drawable/sel_btn_home_page"
            app:layout_constraintBottom_toTopOf="@+id/tvHomePage"
            app:layout_constraintEnd_toStartOf="@id/ivCommunity"
            app:layout_constraintHorizontal_chainStyle="spread_inside"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <com.eyepetizer.android.ui.common.view.TypefaceTextView
            android:id="@+id/tvHomePage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:gravity="center"
            android:text="@string/homepage"
            android:textColor="@color/sel_bottom_navigation_bar_radio_color"
            android:textSize="8sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@id/ivHomePage"
            app:layout_constraintStart_toStartOf="@id/ivHomePage"
            app:layout_constraintTop_toBottomOf="@id/ivHomePage"
            app:typeface="fzlLTypeface" />
    
        <ImageView
            android:id="@+id/ivCommunity"
            android:layout_width="23dp"
            android:layout_height="23dp"
            android:padding="2dp"
            android:src="@drawable/sel_btn_community"
            app:layout_constraintBottom_toTopOf="@id/tvCommunity"
            app:layout_constraintEnd_toStartOf="@id/ivRelease"
            app:layout_constraintStart_toEndOf="@id/ivHomePage"
            app:layout_constraintTop_toTopOf="parent" />
    
        <com.eyepetizer.android.ui.common.view.TypefaceTextView
            android:id="@+id/tvCommunity"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:gravity="center"
            android:text="@string/community"
            android:textColor="@color/sel_bottom_navigation_bar_radio_color"
            android:textSize="8sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@id/ivCommunity"
            app:layout_constraintStart_toStartOf="@id/ivCommunity"
            app:layout_constraintTop_toBottomOf="@+id/ivCommunity"
            app:typeface="fzlLTypeface" />
    
        <ImageView
            android:id="@+id/ivRelease"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:src="@drawable/btn_release_normal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/ivNotification"
            app:layout_constraintStart_toEndOf="@id/ivCommunity"
            app:layout_constraintTop_toTopOf="parent" />
    
        <ImageView
            android:id="@+id/ivNotification"
            android:layout_width="23dp"
            android:layout_height="23dp"
            android:padding="1dp"
            android:src="@drawable/sel_btn_notification"
            app:layout_constraintBottom_toTopOf="@id/tvNotification"
            app:layout_constraintEnd_toStartOf="@id/ivMine"
            app:layout_constraintStart_toEndOf="@id/ivRelease"
            app:layout_constraintTop_toTopOf="parent" />
    
        <com.eyepetizer.android.ui.common.view.TypefaceTextView
            android:id="@+id/tvNotification"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:gravity="center"
            android:text="@string/notification"
            android:textColor="@color/sel_bottom_navigation_bar_radio_color"
            android:textSize="8sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@id/ivNotification"
            app:layout_constraintStart_toStartOf="@id/ivNotification"
            app:layout_constraintTop_toBottomOf="@+id/ivNotification"
            app:typeface="fzlLTypeface" />
    
        <ImageView
            android:id="@+id/ivMine"
            android:layout_width="23dp"
            android:layout_height="23dp"
            android:padding="2dp"
            android:src="@drawable/sel_btn_mine"
            app:layout_constraintBottom_toTopOf="@id/tvMine"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/ivNotification"
            app:layout_constraintTop_toTopOf="parent" />
    
        <com.eyepetizer.android.ui.common.view.TypefaceTextView
            android:id="@+id/tvMine"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="false"
            android:gravity="center"
            android:text="@string/mine"
            android:textColor="@color/sel_bottom_navigation_bar_radio_color"
            android:textSize="8sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@id/ivMine"
            app:layout_constraintStart_toStartOf="@id/ivMine"
            app:layout_constraintTop_toBottomOf="@+id/ivMine"
            app:typeface="fzlLTypeface" />
    
    
        <androidx.constraintlayout.widget.Group
            android:id="@+id/btnHomePage"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/tvHomePage"
            app:layout_constraintEnd_toEndOf="@id/ivHomePage"
            app:layout_constraintStart_toStartOf="@id/ivHomePage"
            app:layout_constraintTop_toTopOf="@+id/ivHomePage"
            tools:background="@color/blackAlpha50" />
    
        <androidx.constraintlayout.widget.Group
            android:id="@+id/btnCommunity"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/tvCommunity"
            app:layout_constraintEnd_toEndOf="@id/ivCommunity"
            app:layout_constraintStart_toStartOf="@id/ivCommunity"
            app:layout_constraintTop_toTopOf="@+id/ivCommunity"
            tools:background="@color/blackAlpha50" />
    
        <androidx.constraintlayout.widget.Group
            android:id="@+id/btnNotification"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/tvNotification"
            app:layout_constraintEnd_toEndOf="@id/ivNotification"
            app:layout_constraintStart_toStartOf="@id/ivNotification"
            app:layout_constraintTop_toTopOf="@+id/ivNotification"
            tools:background="@color/blackAlpha50" />
    
        <androidx.constraintlayout.widget.Group
            android:id="@+id/btnMine"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="@+id/tvMine"
            app:layout_constraintEnd_toEndOf="@id/ivMine"
            app:layout_constraintStart_toStartOf="@id/ivMine"
            app:layout_constraintTop_toTopOf="@+id/ivMine"
            tools:background="@color/blackAlpha50" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    11 FlycoTabLayout_Lib 的使用
    12 GSYVideoPlayer 播放器的使用
    https://codechina.csdn.net/mirrors/CarGuo/GSYVideoPlayer
    主要自定义 三个视频类型
    一个列表
    一个是详情里面
    一个是单独界面的详情

    13.多个点击事件的处理

    fun setOnClickListener(vararg v: View?, block: View.() -> Unit) {
    val listener = View.OnClickListener { it.block() }
    v.forEach { it?.setOnClickListener(listener) }
    }

    setOnClickListener(
    ivMore, ivAvatar, tvLoginTips, tvFavorites, tvCache, tvFollow, tvWatchRecord, tvNotificationToggle,
    tvMyBadge, tvFeedback, tvContribute, tvVersionNumber, rootView, llScrollViewContent
    ) {
    when (this) {
    ivMore -> SettingActivity.start(activity)

                ivAvatar, tvLoginTips, tvFavorites, tvCache, tvFollow, tvWatchRecord, tvNotificationToggle, tvMyBadge -> {
                    LoginActivity.start(activity)
                }
                tvContribute -> {
                    WebViewActivity.start(activity, WebViewActivity.DEFAULT_TITLE, Const.Url.AUTHOR_OPEN, false, false)
                }
                tvFeedback -> {
                    WebViewActivity.start(activity, WebViewActivity.DEFAULT_TITLE, WebViewActivity.DEFAULT_URL, true, false, MODE_SONIC_WITH_OFFLINE_CACHE)
                }
                tvVersionNumber -> {
                    WebViewActivity.start(activity, WebViewActivity.DEFAULT_TITLE, WebViewActivity.DEFAULT_URL, true, false, MODE_SONIC_WITH_OFFLINE_CACHE)
                }
                this@MineFragment.rootView, llScrollViewContent -> {
                    MobclickAgent.onEvent(activity, Const.Mobclick.EVENT4)
                    AboutActivity.start(activity)
                }
    
                else -> {
                }
            }
        }
    

    14 携程+kolint +Retrofit网络请求

    基础

    object ServiceCreator {
    
        const val BASE_URL = "http://baobab.kaiyanapp.com/"
    
        val httpClient = OkHttpClient.Builder()
            .addInterceptor(LoggingInterceptor())
            .addInterceptor(HeaderInterceptor())
            .addInterceptor(BasicParamsInterceptor())
            .build()
    
        private val builder = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(httpClient)
            .addConverterFactory(ScalarsConverterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().registerTypeAdapterFactory(GsonTypeAdapterFactory()).create()))
    
        private val retrofit = builder.build()
    
        fun <T> create(serviceClass: Class<T>): T = retrofit.create(serviceClass)
    }
    interface MainPageService {
    
        /**
         * 首页-发现列表
         */
        @GET
        fun getDiscovery(@Url url: String): Call<Discovery>
    }
    

    然后在封装

     suspend fun refreshVideoRelatedAndVideoReplies(videoId: Long, repliesUrl: String) = requestVideoRelatedAndVideoReplies(videoId, repliesUrl)
    
        suspend fun refreshVideoDetail(videoId: Long, repliesUrl: String) = requestVideoDetail(videoId, repliesUrl)
    
        private suspend fun requestVideoReplies(url: String) = withContext(Dispatchers.IO) {
            coroutineScope {
                val deferredVideoReplies = async { network.fetchVideoReplies(url) }
                val videoReplies = deferredVideoReplies.await()
                videoReplies
            }
        }
    
        private suspend fun requestVideoRelatedAndVideoReplies(videoId: Long, repliesUrl: String) = withContext(Dispatchers.IO) {
            coroutineScope {
                val deferredVideoRelated = async { network.fetchVideoRelated(videoId) }
                val deferredVideoReplies = async { network.fetchVideoReplies(repliesUrl) }
                val videoRelated = deferredVideoRelated.await()
                val videoReplies = deferredVideoReplies.await()
                val videoDetail = VideoDetail(null, videoRelated, videoReplies)
                videoDetail
            }
        }
    

    返回neiwork的里面的内容

      private suspend fun requestHotSearch() = withContext(Dispatchers.IO) {
            val response = eyepetizerNetwork.fetchHotSearch()
            mainPageDao.cacheHotSearch(response)
            response
        }
    
        companion object {
    
            private var repository: MainPageRepository? = null
    
            fun getInstance(dao: MainPageDao, network: EyepetizerNetwork): MainPageRepository {
                if (repository == null) {
                    synchronized(MainPageRepository::class.java) {
                        if (repository == null) {
                            repository = MainPageRepository(dao, network)
                        }
                    }
                }
    
                return repository!!
            }
        }
    

    解决使用携程就行了

    相关文章

      网友评论

          本文标题:完整app -- Eyepetizer 学习

          本文链接:https://www.haomeiwen.com/subject/hycvkltx.html