Commit c4202080 by 万齐军

feature: 倾诉咨询师视频页面

parent bd9a79ff
......@@ -170,6 +170,9 @@ android {
packagingOptions {
exclude 'META-INF/proguard/coroutines.pro'
}
dataBinding{
enabled true
}
}
......@@ -249,4 +252,6 @@ dependencies {
implementation rootProject.ext.dependencies["retrofit-url-manager"]
kapt 'com.alibaba:arouter-compiler:1.2.2'
implementation "androidx.fragment:fragment:1.2.4"
implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
}
......@@ -148,7 +148,8 @@ class MainActivity : BaseLceActivity<DemoContract.View, DemoContract.Presenter>(
}
bt_to_confide.setOnClickListener {
// YDLavManager.instances.login("1193016")
startActivity(Intent(this, ConfideHomeActivity::class.java))
// startActivity(Intent(this, ConfideHomeActivity::class.java))
ARouter.getInstance().build("/confide/expert_video").navigation()
}
ModularServiceManager.provide(IConsultantService::class.java).requestGuideData()
......
......@@ -9,7 +9,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m
org.gradle.jvmargs=-Xmx4096m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
......
......@@ -50,6 +50,9 @@ android {
buildConfigField "String", "AGORA_APPID", '"3387e9b251f3491e9221a9877e8f7830"'
}
}
dataBinding{
enabled true
}
publishNonDefault true
productFlavors {
......@@ -89,6 +92,7 @@ dependencies {
api project(':m-audioim')
api project(":ydl-pay")
api project(':ydl-webview')
api project(':ydl-utils')
implementation modularPublication('com.ydl:m-im-api')
implementation modularPublication('com.ydl:m-user-api')
implementation modularPublication('com.ydl:m-confide-api')
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ydl.confide" >
package="com.ydl.confide">
<application>
<activity android:name=".home.ConfideHomeActivity"
<activity
android:name=".home.ConfideHomeActivity"
android:screenOrientation="portrait"
android:theme="@style/confide_NoTitleTheme"
>
</activity>
android:theme="@style/confide_NoTitleTheme"/>
<activity
android:name=".intro.ExpertIntroActivity"
android:screenOrientation="portrait" />
</application>
</manifest>
package com.ydl.confide.intro
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.viewpager2.widget.ViewPager2
import com.alibaba.android.arouter.facade.annotation.Route
import com.ydl.confide.R
import com.ydl.confide.databinding.ActivityExpertIntroBinding
@Route(path = "/confide/expert_video")
class ExpertIntroActivity : AppCompatActivity() {
private lateinit var binding: ActivityExpertIntroBinding
private lateinit var adapter: IntroAdapter
private val data = mutableListOf<VideoViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_expert_intro)
if (Build.VERSION.SDK_INT >= 21) {
val decorView = window.decorView
val option = (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
decorView.systemUiVisibility = option
window.statusBarColor = Color.TRANSPARENT
}
binding.ivBack.setOnClickListener { onBackPressed() }
data.add(VideoViewModel())
data.add(VideoViewModel())
data.add(VideoViewModel())
data.add(VideoViewModel())
data.add(VideoViewModel())
binding.viewPager.orientation = ViewPager2.ORIENTATION_VERTICAL
binding.viewPager.offscreenPageLimit = 1
adapter = IntroAdapter(this, data, this)
binding.viewPager.adapter = adapter
binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
adapter.onSelect(position)
if (position == data.size - 1) {
loadMore()
}
}
})
}
private fun loadMore() {
data.add(VideoViewModel())
data.add(VideoViewModel())
data.add(VideoViewModel())
data.add(VideoViewModel())
data.add(VideoViewModel())
adapter.notifyItemRangeInserted(data.size - 5, 5)
}
}
\ No newline at end of file
package com.ydl.confide.intro
import android.content.Context
import android.net.Uri
import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import androidx.recyclerview.widget.RecyclerView
import com.dou361.ijkplayer.widget.IjkVideoView
import com.ydl.confide.R
import com.ydl.confide.databinding.ItemExpertIntroBinding
internal class IntroAdapter(
private val context: Context,
private val data: List<VideoViewModel>,
private val lifecycleOwner: LifecycleOwner
) : RecyclerView.Adapter<ItemIntroHolder>(), LifecycleObserver {
private val videoViews = hashMapOf<Int, IjkVideoView>()
init {
lifecycleOwner.lifecycle.addObserver(this)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemIntroHolder {
val binding = DataBindingUtil.inflate<ItemExpertIntroBinding>(
LayoutInflater.from(parent.context),
R.layout.item_expert_intro,
parent,
false
)
val holder = ItemIntroHolder(binding)
lifecycleOwner.lifecycle.addObserver(holder)
return holder
}
override fun onBindViewHolder(holder: ItemIntroHolder, position: Int) {
holder.onBind()
val item = data[position]
holder.binding.item = item
}
override fun onViewAttachedToWindow(holder: ItemIntroHolder) {
val adapterPosition = holder.adapterPosition
val videoView = IjkVideoView(context)
videoView.setVideoURI(Uri.parse("https://video.ydlcdn.com/2020/04/01/ac2e4bb4e3ac8e2f0eca41e2d49c8484.mp4"))
videoViews.put(adapterPosition, videoView)
holder.onAttach(videoView)
}
override fun onViewDetachedFromWindow(holder: ItemIntroHolder) {
super.onViewDetachedFromWindow(holder)
val adapterPosition = holder.adapterPosition
val video = videoViews.get(adapterPosition)
video?.release(true)
videoViews.remove(adapterPosition)
lifecycleOwner.lifecycle.removeObserver(holder)
holder.onDetach()
}
override fun getItemCount(): Int {
return data.size
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private fun onDestroy() {
for (entry in videoViews.entries) {
entry.value.release(true)
}
}
fun onSelect(position: Int) {
Log.i("qwe", "" + videoViews.size)
for (entry in videoViews.entries) {
if (entry.key == position) {
entry.value.seekTo(0)
entry.value.start()
} else {
entry.value.pause()
}
}
}
}
\ No newline at end of file
package com.ydl.confide.intro
import android.util.Log
import android.view.View
import android.widget.SeekBar
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.databinding.ObservableInt
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.recyclerview.widget.RecyclerView
import com.dou361.ijkplayer.widget.IjkVideoView
import com.ydl.confide.databinding.ItemExpertIntroBinding
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.util.concurrent.TimeUnit
internal class ItemIntroHolder(binding: ItemExpertIntroBinding) :
BindingViewHolder<ItemExpertIntroBinding>(binding), LifecycleObserver {
private var disposable: Disposable? = null
private var video: IjkVideoView? = null
fun onDetach() {
stopTiming()
video?.release(true)
}
fun onBind() {
binding.btnCall.setOnClickListener { }
binding.btnChat.setOnClickListener { }
binding.btnEvaluate.setOnClickListener { }
binding.btnShare.setOnClickListener { }
binding.videoView.setOnClickListener {
video?.pause()
binding.ivPlay.visibility = View.VISIBLE
}
binding.ivPlay.setOnClickListener {
video?.start()
binding.ivPlay.visibility = View.GONE
}
binding.seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
if (seekBar != null) {
video?.seekTo(seekBar.progress)
video?.start()
binding.ivPlay.visibility = View.GONE
}
}
})
}
fun onAttach(videoView: IjkVideoView) {
this.video = videoView
binding.videoView.addView(videoView)
video?.setOnPreparedListener { player ->
Log.d("qweqwe", "${player.videoHeight},${player.videoWidth},${player.duration}")
val duration = player.duration.toInt()
if (duration > 0) {
binding.seekbar.max = duration
} else {
binding.seekbar.visibility = View.GONE
}
}
video?.setOnInfoListener { mp, what, extra ->
Log.d("qweqwe", "${what},${extra}")
return@setOnInfoListener false
}
video?.setOnCompletionListener { stopTiming() }
startTiming()
}
private fun startTiming() {
disposable = Observable.interval(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.computation())
.subscribe {
val pos = (video?.mMediaPlayer as IjkMediaPlayer?)?.currentPosition ?: 0
if (pos > 0) {
binding.seekbar.progress = pos.toInt()// video.bufferPercentage
}
}
}
private fun stopTiming() {
disposable?.dispose()
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
private fun onResume() {
video?.onResume()
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
private fun onPause() {
video?.onPause()
}
}
class VideoViewModel {
val name = ObservableField<String>("")
val avatar = ObservableField<String>("")
val count = ObservableInt()
val intro = ObservableField<String>("")
val tag = ObservableField<String>("")
}
open class BindingViewHolder<T : ViewDataBinding>(val binding: T) :
RecyclerView.ViewHolder(binding.root)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="4dp" />
<solid android:color="#59FFFFFF" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="4dp" />
<solid android:color="@color/white" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="4dp" />
<solid android:color="@color/white" />
</shape>
</clip>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="@color/white" />
<size android:width="6dp" android:height="6dp" />
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="@color/white" />
<size android:width="6dp" android:height="6dp" />
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivBack"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="24dp"
android:padding="12dp"
android:src="@drawable/confide_back"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:shape="@{1}"
app:shapeBg="@{0x33ff0000}"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:gravity="center"
android:padding="8dp"
android:paddingHorizontal="8dp"
android:paddingVertical="5dp"
android:text="倾诉记录"
android:textColor="@color/white"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@+id/ivBack"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/ivBack"
app:shapeBg="@{0x26f00000}"
app:shapeRadius="@{15}"
app:shapeStrokeColor="@{0xFFFFFF}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="item"
type="com.ydl.confide.intro.VideoViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black">
<FrameLayout
android:id="@+id/videoView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivPlay"
android:layout_width="76dp"
android:layout_height="76dp"
android:src="@drawable/ic_video_play"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="23dp"
android:maxHeight="4dp"
android:paddingStart="0dp"
android:paddingEnd="0dp"
android:progressDrawable="@drawable/confide_seekbar_style"
android:splitTrack="false"
android:thumb="@drawable/confide_seekbar_thumb"
app:layout_constraintBottom_toTopOf="@+id/btnCall"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/btnCall"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginBottom="32dp"
android:gravity="center"
android:text="通话中"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/tvTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginBottom="60dp"
android:text="@{item.tag}"
android:textColor="#99FFFFFF"
android:textSize="13sp"
app:layout_constraintBottom_toTopOf="@+id/btnCall"
app:layout_constraintLeft_toLeftOf="parent"
tools:text="tag|tag|tag" />
<TextView
android:id="@+id/tvIntro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@{item.intro}"
android:textColor="@color/white"
android:textSize="15sp"
app:layout_constraintBottom_toTopOf="@+id/tvTag"
app:layout_constraintLeft_toLeftOf="@+id/tvTag"
tools:text="tag|tag|tag" />
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="@{item.name}"
android:textColor="@color/white"
android:textSize="19sp"
app:layout_constraintBottom_toTopOf="@+id/tvIntro"
app:layout_constraintLeft_toLeftOf="@+id/tvTag"
tools:text="tag|tag|tag" />
<TextView
android:id="@+id/tvConfideCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="@+id/tvName"
app:layout_constraintLeft_toRightOf="@+id/tvName"
tools:text="tag|tag|tag" />
<TextView
android:id="@+id/btnShare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="18dp"
android:layout_marginBottom="56dp"
android:drawableTop="@drawable/ic_video_share"
android:text="分享"
android:textColor="@color/white"
android:textSize="11sp"
app:layout_constraintBottom_toTopOf="@+id/btnCall"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/btnEvaluate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="18dp"
android:layout_marginBottom="20dp"
android:drawableTop="@drawable/ic_video_eval"
android:text="评价"
android:textColor="@color/white"
android:textSize="11sp"
app:layout_constraintBottom_toTopOf="@+id/btnShare"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/btnChat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="18dp"
android:layout_marginBottom="20dp"
android:drawableTop="@drawable/ic_chat"
android:text="私聊"
android:textColor="@color/white"
android:textSize="11sp"
app:layout_constraintBottom_toTopOf="@+id/btnEvaluate"
app:layout_constraintRight_toRightOf="parent" />
<ImageView
android:layout_width="46dp"
android:layout_height="46dp"
android:layout_marginRight="10dp"
app:layout_constraintBottom_toTopOf="@+id/btnChat"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
......@@ -29,6 +29,10 @@ android {
abortOnError false
}
dataBinding {
enabled true
}
buildTypes {
release {
minifyEnabled false
......@@ -65,4 +69,5 @@ dependencies {
implementation(rootProject.ext.dependencies["arouter"])
kapt(rootProject.ext.dependencies["arouter-compiler"])
compileOnly(rootProject.ext.dependencies["systembartint"])
implementation "com.ydl:ydl-image:1.0.10-SNAPSHOT"
}
package com.yidianling.common.binding
import android.graphics.Color
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.PaintDrawable
import android.graphics.drawable.shapes.RectShape
import android.graphics.drawable.shapes.RoundRectShape
import android.view.View
import android.widget.ImageView
import androidx.databinding.BindingAdapter
import com.ydl.ydl_image.module.GlideApp
@BindingAdapter("imageUrl")
fun setImageUrl(imageView: ImageView, url: String?) {
if (url.isNullOrEmpty()) return
GlideApp.with(imageView).load(url).into(imageView)
}
@BindingAdapter(
value = [
"shapeBg",
"shapeStrokeColor",
"shapeStrokeWidth",
"shapeRadius",
"shape"
],
requireAll = false
)
fun View.setCustomStyle(
shapeBg: Int = Color.TRANSPARENT, // 背景颜色
shapeStrokeColor: Int = Color.TRANSPARENT, // 边框颜色
shapeStrokeWidth: Float = 0f, // 边框宽度
shapeRadius: Float = 0f, // 圆角宽度
shape: Int = GradientDrawable.RECTANGLE // Shape样式 默认矩形
) {
val gradientDrawable: GradientDrawable = if (background as? GradientDrawable == null) {
GradientDrawable()
} else {
background as GradientDrawable
}
gradientDrawable.setColor(shapeBg)
gradientDrawable.setStroke(
shapeStrokeWidth.toInt(),
shapeStrokeColor
)
val radius = resources.displayMetrics.density * shapeRadius
gradientDrawable.cornerRadii = floatArrayOf(
radius,
radius,
radius,
radius,
radius,
radius,
radius,
radius
)
when (shape) {
GradientDrawable.RECTANGLE -> gradientDrawable.shape = GradientDrawable.RECTANGLE
GradientDrawable.OVAL -> gradientDrawable.shape = GradientDrawable.OVAL
GradientDrawable.LINE -> gradientDrawable.shape = GradientDrawable.LINE
GradientDrawable.RING -> gradientDrawable.shape = GradientDrawable.RING
else -> gradientDrawable.shape = GradientDrawable.RECTANGLE
}
background = gradientDrawable
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment