HtmlRecycler Converts a simple html page into A RecyclerView of Native android widgets.
Converts a simple html page into A RecyclerView
of native android widgets powered by Jsoup library and inspired by Medium Textview.
Note
This library was design and developed by ME and we use this in our application which depends on a Content Management system and was never intended to replace browsers or act as one. this library simply gave us more control over html page than
WebView
dependencies {
implementation 'com.github.m7mdra:HtmlRecycler:0.1.11'
}
This project is distributed using jitpack. Make sure you add it as a maven repository to your build.gradle
allprojects {
repositories {
maven {
url 'https://jitpack.io'
}
}
}
git clone
the repository and build the app
module.val networkSource = NetworkSource("https://gist.githubusercontent.com/m7mdra/f22c62bc6941e08064b4fbceb4832a90/raw/ea8574d986635cf214541f1f5702ef37cc731aaf/article.html")
HtmlRecycler.Builder(this@MainActivity)
.setSource(networkSource)
.setAdapter(DefaultElementsAdapter(this@MainActivity) { element, i, view ->
}})
.setRecyclerView(recyclerView)
.setLoadingCallback(object : HtmlRecycler.LoadCallback {
override fun onLoadingStart() {
progressBar.visibility = View.VISIBLE
}
override fun onLoaded(document: Document?) {
progressBar.visibility = View.GONE
}
})
.build()
The above code uses the existing implementation of DefaultElementsAdapter
which extends
ElementsAdapter
class which inherently is a RecylcerView Adpater
the DefaultElementsAdapter
uses a layout resources files defined by me but they not styled probably and are very buggy (especially the video, audio and iframe ones).
Want to create your own adapter? just simply extend ElementsAdapter
and override methods:
class BetterImplementationThanTheAuthorsAdapter : ElementsAdapter() {
override fun onCreateElement(parent: ViewGroup, elementType: ElementType): RecyclerView.ViewHolder {
when (elementType) {
ElementType.Paragraph -> {
return ParagraphViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.row_paragarph, parent, false))
}
// Define other elements here
}
}
override fun onBindElement(holder: RecyclerView.ViewHolder, position: Int) {
val element = elements[position] //current element
if (holder is ParagraphViewHolder){
val paragraphElement = element as ParagraphElement
holder.paragraphText.text= paragraphElement.text
}
}
}
}
Then replace the default adapter with your adapter:
HtmlRecycler.Builder(this)
.setSource(StringSource(Data.data))
.setAdapter(BetterImplementationThanTheAuthorsAdapter()) // this is a custom adapter
.setRecyclerView(recyclerView)
.build()
Data can come from different sources, the library support the following:
UI thread
by default so you have to run it on different thread or write your own Source Implementation )Simply implement the Source
interface which will return a Document
of the parsed Source
:
class FileSource(val file: File) : Source {
override fun get(): Document {
return Jsoup.parse(file, "UTF-8")
}
}
In DefaultElemetsAdapter
class at line #27 l i defined a higher-order-function in the constructor method (which dose the same as defining an interface) and on line #75 we envoke the method passing our element and the position of the clicked view.
the library will mark any unimplemented element as UnknownElement
and will delegate it to the android.text.Html#fromHtml
class to convert it Spans
and will be displayed on TextView
NetworkSource
to run on UI thread
without crashing.Table
Div
Section
Superscript
and Subscrpit
android.text.Html
class rather than handled by the libraryPR are welcome just use crtl+alt+L or (command + alt+L for mac ... idk if right) after every time your finish write code to format it.
if you are using this library in your project let me by sending an email at [email protected] know and i will post it here.