I have an activity which I will show xml for below, containing a webView inside an appBarLayout. Now to be frank, I don't know where the appBarLayout came from because I dont remember adding it in. But anyways, the screen has stacked in the following order top->bottom: a textView, a videoView, and a webView. So the HTML being displayed in the webview is only maybe the bottom half of the screen. Below the xml snippet, I have a image of how this looks from the design POV. The closest I ever got to scrolling is if the webView and friends are NOT children of appBarLayout but then the webview takes up entire screen which is not desirable.
I admit, this probably is setup wrong but I will gladly take whatever advice you have and suggestions on editing the way this is arranged/configured.
Activity XML
<androidx.coordinatorlayout.widget.CoordinatorLayout 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="match_parent"
tools:context=".Lesson">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:isScrollContainer="true"
android:scrollbars="vertical"
android:theme="#style/Theme.ProjectName.AppBarOverlay"
android:verticalScrollbarPosition="right">
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="64dp"
android:fontFamily="#font/reem_kufi"
android:gravity="center"
android:isScrollContainer="false"
android:linksClickable="true"
android:text="Title Goes Here"
android:textAlignment="center"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:textStyle="bold" />
<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
android:id="#+id/videoView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<WebView
android:id="#+id/lessonContentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fadeScrollbars="true"
android:isScrollContainer="true"
android:nestedScrollingEnabled="true"
android:overScrollMode="ifContentScrolls"
android:persistentDrawingCache="scrolling"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layout_scrollFlags="scroll" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Kotlin File
class Lesson : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityLessonBinding
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityLessonBinding.inflate(layoutInflater)
setContentView(binding.root)
webView = findViewById(R.id.lessonContentView)
if(webView != null){
webView.requestFocus()
webView.settings.javaScriptEnabled = true
webView.isSoundEffectsEnabled = true
webView.isVerticalScrollBarEnabled = true
webView.settings.loadWithOverviewMode = true
webView.settings.allowContentAccess = true
webView.settings.domStorageEnabled = true
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
if (url != null) {
view?.loadUrl(url)
}
return true
}
}
webView.loadUrl("file:///android_asset/lesson.html")
}
val youTubePlayerView: YouTubePlayerView? = findViewById(R.id.videoView)
if (youTubePlayerView != null) {
lifecycle.addObserver(youTubePlayerView)
}
youTubePlayerView?.addYouTubePlayerListener(object : AbstractYouTubePlayerListener() {
override fun onReady(youTubePlayer: YouTubePlayer) {
val videoId = "yJdkdiAly0w"
youTubePlayer.cueVideo(videoId, 0F)
}
})
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_lesson)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
}
Component Tree & Design
How it looks now
How it looked when I got it to scroll but not how I wanted
I have already tried the advice given on several posts here on StackOverflow so please do not just mark as Duplicate and run off. Probably a quarter of the code in the project right now is from me trying to get scrolling to work with the advice of this site.
I have tried messing with all the scroll attributes for basically every view on here.
I have added StackOverflow recommended items such as the app:layout_behavior and these webview settings below:
webView.isVerticalScrollBarEnabled = true
webView.settings.loadWithOverviewMode = true
webView.settings.allowContentAccess = true
When I got it to scroll but wasnt correct, shown in image link earlier, I had removed all the views from the appBarLayout parent making everything a direct child of what this says is a "CoordinatorLayout".
Received help outside of SO (Discord) and I will go over the changes below.
First, I removed the appBarLayout. As originally mentioned, I wasn't even sure about it or how it got there as a parent of everything. I also removed ITS PARENT the coordinatorLayout by changing it to a constraintLayout. This is the parent of my 3 needed pieces (text, video, web) all stacked on top of each other. A few attributes were removed from the xml as well.
Please feel free to comment if you see this in the future and have questions about how I solved this.
<?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:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Lesson">
<com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
android:id="#+id/videoView"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView2" />
<TextView
android:id="#+id/textView2"
android:layout_width="412dp"
android:layout_height="54dp"
android:fontFamily="#font/reem_kufi"
android:gravity="center"
android:isScrollContainer="false"
android:linksClickable="true"
android:text="Winds & Temperatures Aloft"
android:textAlignment="center"
android:textColor="#000000"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<WebView
android:id="#+id/lessonContentView"
android:layout_width="412dp"
android:layout_height="0dp"
android:fadeScrollbars="true"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/videoView"
app:layout_constraintVertical_bias="0.483"
app:layout_scrollFlags="scroll" />
</androidx.constraintlayout.widget.ConstraintLayout>
Related
I'm trying to implement a document tree using a RecyclerView. Because the tree is expandable, I'm using a custom adapter for it. All of the layout items in the RecyclerView are set to WRAP_CONTENT width, along with the RecyclerView itself. Because the labels in the items can be long and nested, I want the list to be horizontally scrollable to see the clipped items, and the list orientation to be vertical. Comment if you need anything else.
branch.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:padding="10dp"
android:id="#+id/title"
android:gravity="center"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/arrow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/ic_baseline_keyboard_arrow_down_24"/>
</LinearLayout>
activity
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context=".TreeActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</HorizontalScrollView>
Binding the view(The adapter is separately managed)
class BranchViewHolder(val branchBinding: BranchBinding) : TreeViewBinder.ViewHolder(branchBinding.root)
override fun getLayoutId(): Int = R.layout.branch
override fun provideViewHolder(itemView: View?): BranchViewHolder = BranchViewHolder(BranchBinding.bind(itemView!!))
override fun bindView(p0: BranchViewHolder?, p1: Int, p2: TreeNode<*>?) {
Log.i(TAG, "bindView: ${p2?.isExpand}")
val rotateDegree = if (p2?.isExpand == true) -90 else 0
p0?.branchBinding?.arrow?.rotation = rotateDegree.toFloat()
with(p2?.content as Branch) {
p0?.branchBinding?.title?.text = this.name
p0?.itemView?.layoutParams= RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
}
Screenshot
Problem - Want to horizontally scroll
Add app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" to your RecyclerView.
For example if you want to scroll the items horizontally, try this one :
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
Don't forget to add the orientation for the vertical / horizontal scroll.
I have surprisingly been stuck on this one for a little while.
User Story:
The user should see a Loading Dialog that can be reused through the application with a transparent background so you only see the progress spinner and the text under the progress spinner.
Currently, I have a DialogFragment that inflates this XML to present itself:
<?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="wrap_content"
android:background="#android:color/transparent">
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="1"
android:background="#android:color/transparent"
android:indeterminateDrawable="#drawable/loading_spinner"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.499" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:alpha="1"
android:background="#android:color/transparent"
android:text="Loading..."
android:textColor="#FFFFFF"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/progressBar" />
</androidx.constraintlayout.widget.ConstraintLayout>
I am trying to set the transparency in the background and have had these results:
alpha set changes children elements to transparent as well
above XML setting does nothing and shows a white background
Setting it programmatically(See below) also does nothing and displays it white.
LoadingDialog():
class LoadingDialog(): DialogFragment() {
private var _binding: FragmentLoadingDialogBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.dialog?.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState:Bundle?
): View? {
_binding = FragmentLoadingDialogBinding.inflate(inflater, container, false)
return binding.root
}
//Always do this in Dialog to maintain memory management
override fun onDestroy() {
super.onDestroy()
_binding = null
}
}
How can I get the above LoadingDialog to present the Loading Progress Spinner and the Text without the white background?
I think you should call onCreate() method before setting the background to transparent after which you should set the view for your dialog. Try this
val dialogBinding = // inflate dialog here using dataBinding for example
val customDialog = AlertDialog.Builder(this, 0).create() // works with other dialogs as well
customDialog.apply {
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
setView(dialogBinding?.root)
}.show()
I hope this helps you solve your problem. For more information about Dialogs in Android, please refer to my article on section.io
something else, consider removing the transparent background on your root viewGroup as shown below
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
...
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
edit to
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
...
android:layout_width="match_parent"
android:layout_height="wrap_content">
I am making app using API and fetched all the data perfectly. I also have search bar on recycler view. Now I want to save the search history which user searches on the app. I have followed the solutions from stackoverflow but I am not able to save the history.
Search history in Android quick search
I want to know that where I have to make searchable.xml ? Also I am using edittext for performing search in my code so I have remove edittext and replace with searchable?
I little confused in using and setting up the content provider.
My xml file:
<?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="match_parent"
tools:context=".ui.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ProgressBar
android:id="#+id/progress_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:visibility="gone"/>
<TextView
android:id="#+id/txt_error_popular"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/connection_problem"
android:visibility="gone"/>
<EditText
android:id="#+id/search_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionSearch"
android:inputType="text"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:hint="#string/search_for_something"
android:layout_marginBottom="4dp"
android:importantForAutofill="no" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_photos"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:scrollbars="vertical">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
My main activity where I am performing search:
search(DEFAULT_SEARCH)
search_box?.setOnEditorActionListener(object : TextView.OnEditorActionListener{
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if (actionId == EditorInfo.IME_ACTION_SEARCH){
val searchTerm = search_box.text.trim()
if (searchTerm.isNotEmpty()){
rv_photos?.scrollToPosition(0)
photoAdapter.submitList(null)
search(searchTerm.toString())
currentFocus?.let {
val inputManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputManager.hideSoftInputFromWindow(it.windowToken, HIDE_NOT_ALWAYS)
}
}
return true
}
return false
}
})
}
private fun search(searchTerm: String){
viewModel.performSearch(searchTerm)
}
Now I just want to save the recent search?
Just use roomDb to store your search history and whenever the user clicks on the search box fetch the search list
Check this latest codelab by google which guides you through roomDb
https://developer.android.com/codelabs/android-room-with-a-view-kotlin#0
I don't know if it is a bug or i am making some mistake but when i set Explode animation when opening an Activity it animates like a Slide animation from top to bottom. I did some trial and error and it turns out that when i use a custom background color in the root layout in the xml file this unexpected behavior occures. When i remove the background color everything works as expected.
Can anyone tell me what's going on here??? Because it is important for me to set background color in the root layout.
Here's a sample of my xml code:
<?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="match_parent"
android:background="#000000" // This causes the unexpected behavior.
tools:context=".ExplodeActivity">
<ImageView
android:id="#+id/imageView2"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/b" />
<Button
android:id="#+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This is the ExplodeActivity 's onCreate method where i am assigning the animation:
class ExplodeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_explode)
val enterTransition = Explode()
enterTransition.duration = 500
window.enterTransition = enterTransition
}
}
Here's the previous activity's code which responsible for starting the ExplodeActivity:
val options = ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
val intent = Intent(this, ExplodeActivity::class.java)
startActivity(intent, options)
I am experiencing weird shadow behavior, when animation of parent viewGroup is taking place on Android Pie. It is happening on all phones with android 9.0 I have. Except for emulator.
So, the shadow is blinking and kinda offset.
To simulate, I have this simple Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<View>(R.id.animated_item).startAnimation(AlphaAnimation(0.9f, 1.0f).apply {
duration = 500
repeatCount = Animation.INFINITE
repeatMode = Animation.REVERSE
})
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View
android:layout_width="120dp"
android:layout_height="200dp"
android:layout_margin="8dp"
android:background="#fff"
android:elevation="6dp" />
</FrameLayout>
<FrameLayout
android:id="#+id/animated_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View
android:layout_width="120dp"
android:layout_height="200dp"
android:layout_margin="8dp"
android:background="#fff"
android:elevation="6dp" />
</FrameLayout>
</LinearLayout>
Result:
Probably, it's too late, but to get rid of this effect I had to apply animation to the View with elevation itself, but not to its parent layout.