콘텐츠 메인

- 채널 검색 추가
This commit is contained in:
klaus 2025-01-09 03:54:02 +09:00
parent d00a5475ce
commit 2667e29bb9
4 changed files with 225 additions and 0 deletions

View File

@ -48,6 +48,7 @@ import kr.co.vividnext.sodalive.explorer.ExplorerSectionAdapter
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.explorer.profile.series.UserProfileSeriesListAdapter import kr.co.vividnext.sodalive.explorer.profile.series.UserProfileSeriesListAdapter
import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.main.MainActivity
import kr.co.vividnext.sodalive.mypage.alarm.AlarmListActivity import kr.co.vividnext.sodalive.mypage.alarm.AlarmListActivity
import kr.co.vividnext.sodalive.settings.event.EventDetailActivity import kr.co.vividnext.sodalive.settings.event.EventDetailActivity
import kr.co.vividnext.sodalive.settings.notification.MemberRole import kr.co.vividnext.sodalive.settings.notification.MemberRole
@ -149,6 +150,10 @@ class AudioContentMainFragment : BaseFragment<FragmentAudioContentMainBinding>(
) )
) )
} }
binding.flSearchChannel.setOnClickListener {
(requireActivity() as MainActivity).showSearchBar()
}
} }
private fun setupCreatorRank() { private fun setupCreatorRank() {

View File

@ -1,6 +1,7 @@
package kr.co.vividnext.sodalive.main package kr.co.vividnext.sodalive.main
import android.Manifest import android.Manifest
import android.app.Service
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
@ -8,11 +9,14 @@ import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Rect
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.View import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.activity.addCallback
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
@ -21,12 +25,17 @@ import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.session.MediaController import androidx.media3.session.MediaController
import androidx.media3.session.SessionToken import androidx.media3.session.SessionToken
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.load import coil.load
import coil.transform.RoundedCornersTransformation import coil.transform.RoundedCornersTransformation
import com.google.firebase.messaging.FirebaseMessaging import com.google.firebase.messaging.FirebaseMessaging
import com.gun0912.tedpermission.PermissionListener import com.gun0912.tedpermission.PermissionListener
import com.gun0912.tedpermission.normal.TedPermission import com.gun0912.tedpermission.normal.TedPermission
import com.jakewharton.rxbinding4.widget.textChanges
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
@ -40,19 +49,26 @@ import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.ActivityMainBinding import kr.co.vividnext.sodalive.databinding.ActivityMainBinding
import kr.co.vividnext.sodalive.databinding.ItemMainTabBinding import kr.co.vividnext.sodalive.databinding.ItemMainTabBinding
import kr.co.vividnext.sodalive.explorer.ExplorerViewModel
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.live.LiveFragment import kr.co.vividnext.sodalive.live.LiveFragment
import kr.co.vividnext.sodalive.message.MessageFragment import kr.co.vividnext.sodalive.message.MessageFragment
import kr.co.vividnext.sodalive.message.SelectMessageRecipientAdapter
import kr.co.vividnext.sodalive.mypage.MyPageFragment import kr.co.vividnext.sodalive.mypage.MyPageFragment
import kr.co.vividnext.sodalive.settings.event.EventDetailActivity import kr.co.vividnext.sodalive.settings.event.EventDetailActivity
import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import java.util.concurrent.TimeUnit
@UnstableApi @UnstableApi
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) { class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {
private val viewModel: MainViewModel by inject() private val viewModel: MainViewModel by inject()
private val explorerViewModel: ExplorerViewModel by inject()
private lateinit var searchChannelAdapter: SelectMessageRecipientAdapter
private lateinit var imm: InputMethodManager
private lateinit var liveFragment: LiveFragment private lateinit var liveFragment: LiveFragment
private lateinit var loadingDialog: LoadingDialog private lateinit var loadingDialog: LoadingDialog
@ -61,6 +77,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
private var mediaController: MediaController? = null private var mediaController: MediaController? = null
private val handler = Handler(Looper.getMainLooper()) private val handler = Handler(Looper.getMainLooper())
private val audioContentReceiver = AudioContentReceiver() private val audioContentReceiver = AudioContentReceiver()
private var isShowSearchBar = false
private val preferenceChangeListener = private val preferenceChangeListener =
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
@ -174,6 +191,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
imm = getSystemService(
Service.INPUT_METHOD_SERVICE
) as InputMethodManager
checkPermissions() checkPermissions()
pushTokenUpdate() pushTokenUpdate()
gaidUpdate() gaidUpdate()
@ -189,6 +210,15 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
} }
handler.postDelayed({ executeDeeplink(intent) }, 500) handler.postDelayed({ executeDeeplink(intent) }, 500)
onBackPressedDispatcher.addCallback {
if (isShowSearchBar) {
hideSearchBar()
} else {
isEnabled = false
onBackPressedDispatcher.onBackPressed()
}
}
} }
override fun onDestroy() { override fun onDestroy() {
@ -239,6 +269,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
} }
setupBottomTabLayout() setupBottomTabLayout()
setupSearchChannelView()
} }
private fun executeDeeplink(intent: Intent) { private fun executeDeeplink(intent: Intent) {
@ -497,6 +528,96 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
} }
} }
private fun setupSearchChannelView() {
searchChannelAdapter = SelectMessageRecipientAdapter {
hideKeyboard()
val intent = Intent(applicationContext, UserProfileActivity::class.java)
intent.putExtra(Constants.EXTRA_USER_ID, it.id)
startActivity(intent)
}
binding.rvSearchChannel.layoutManager = LinearLayoutManager(
this,
LinearLayoutManager.VERTICAL,
false
)
binding.rvSearchChannel.addItemDecoration(object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
outRect.left = 13.3f.dpToPx().toInt()
outRect.right = 13.3f.dpToPx().toInt()
outRect.top = 13.3f.dpToPx().toInt()
outRect.bottom = 13.3f.dpToPx().toInt()
}
})
binding.rvSearchChannel.adapter = searchChannelAdapter
compositeDisposable.add(
binding.etSearchChannel.textChanges().skip(1)
.debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe {
if (it.length >= 2) {
explorerViewModel.searchChannel(it.toString())
binding.rvSearchChannel.visibility = View.VISIBLE
binding.tvResultX.visibility = View.GONE
} else {
binding.rvSearchChannel.visibility = View.GONE
binding.tvResultX.visibility = View.VISIBLE
}
}
)
explorerViewModel.searchChannelLiveData.observe(this) {
searchChannelAdapter.items.clear()
if (it.isNotEmpty()) {
searchChannelAdapter.items.addAll(it)
binding.rvSearchChannel.visibility = View.VISIBLE
binding.tvResultX.visibility = View.GONE
} else {
binding.rvSearchChannel.visibility = View.GONE
binding.tvResultX.visibility = View.VISIBLE
}
searchChannelAdapter.notifyDataSetChanged()
}
}
private fun hideKeyboard() {
handler.postDelayed({
imm.hideSoftInputFromWindow(
window.decorView.applicationWindowToken,
InputMethodManager.HIDE_NOT_ALWAYS
)
}, 100)
}
private fun hideSearchBar() {
isShowSearchBar = false
binding.nsSearch.visibility = View.GONE
binding.etSearchChannel.setText("")
}
fun showSearchBar() {
isShowSearchBar = true
binding.nsSearch.visibility = View.VISIBLE
binding.etSearchChannel.setText("")
binding.etSearchChannel.requestFocus()
binding.etSearchChannel.post {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.etSearchChannel, InputMethodManager.SHOW_IMPLICIT)
}
}
inner class AudioContentReceiver : BroadcastReceiver() { inner class AudioContentReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
val contentId = intent?.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0) val contentId = intent?.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0)

View File

@ -197,4 +197,71 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" /> android:layout_weight="1" />
</LinearLayout> </LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/ns_search"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/fl_search_channel"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="20dp"
android:background="@drawable/bg_round_corner_6_7_222222_bbbbbb">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_marginStart="21.3dp"
android:contentDescription="@null"
android:src="@drawable/ic_title_search_black" />
<EditText
android:id="@+id/et_search_channel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="@null"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center_vertical"
android:hint="채널명을 입력해보세요"
android:importantForAutofill="no"
android:inputType="textWebEditText"
android:paddingHorizontal="54.67dp"
android:textColor="@color/color_eeeeee"
android:textColorHint="@color/color_eeeeee"
android:textCursorDrawable="@drawable/edit_text_cursor"
android:textSize="13.3sp"
tools:ignore="LabelFor" />
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_search_channel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:nestedScrollingEnabled="false"
android:paddingVertical="20dp"
android:visibility="gone" />
<TextView
android:id="@+id/tv_result_x"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginVertical="40dp"
android:text="검색 결과가 없습니다." />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</RelativeLayout> </RelativeLayout>

View File

@ -64,6 +64,38 @@
android:layout_marginTop="6.7dp" android:layout_marginTop="6.7dp"
android:layout_marginBottom="26.7dp" /> android:layout_marginBottom="26.7dp" />
<RelativeLayout
android:id="@+id/fl_search_channel"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginHorizontal="13.3dp"
android:layout_marginBottom="40dp"
android:background="@drawable/bg_round_corner_6_7_222222_bbbbbb"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical"
android:layout_marginStart="21.3dp"
android:contentDescription="@null"
android:src="@drawable/ic_title_search_black" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="center_vertical"
android:paddingHorizontal="54.67dp"
android:text="채널명을 입력해보세요"
android:textColor="@color/color_eeeeee"
android:textSize="13.3sp" />
</RelativeLayout>
<LinearLayout <LinearLayout
android:id="@+id/ll_creator_rank" android:id="@+id/ll_creator_rank"
android:layout_width="match_parent" android:layout_width="match_parent"