Skip to content

Recipes

James Barr edited this page Jul 23, 2018 · 4 revisions

We've written some recipes that demonstrate how to solve common problems with ViewPump. Read through them to learn about how everything works together. Cut-and-paste these examples freely; that's what they're for.

Simulate AppCompat Behavior

When AppCompat's LayoutInflater attempts to inflate a TextView, it actually instantiates an AppCompatTextView instead. With ViewPump, we can simulate that behavior using a pre-inflation Interceptor. Instead of changing the name of the View to inflate, we could also just instantiate an instance of the new View type and return that.

class AppCompatInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): InflateResult {
    val request = chain.request()
    val viewNameToInflate = viewNameToInflate(request.name())
    return chain.proceed(request.toBuilder().name(viewNameToInflate).build())
  }
    
  private fun viewNameToInflate(requestedViewName: String) = when (requestedViewName) {
    "Button" -> AppCompatButton::class.java.name
    "EditText" -> AppCompatEditText::class.java.name
    "ImageView" -> AppCompatImageView::class.java.name
    "TextView" -> AppCompatTextView::class.java.name
    ...
    else -> requestedViewName
  }
}

Hide Views Without Content Description

In order to encourage more accessible apps, you might consider hiding views with no content description.

class AccessibilityEncouragingInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): InflateResult {
    val result = chain.proceed(chain.request())
    result.view()?.let { 
      if (it.isClickable && it.contentDescription.isNullOrEmpty()) {
        it.visibility = View.INVISIBLE
      }
    }
    return result
  }
}

Draw Over a View

When some sort of condition is met, you might want to highlight a certain view. This is how you could draw the bounds of all non-ViewGroups.

class ViewBoundsInterceptor : Interceptor {
  override fun intercept(chain: Chain): InflateResult {
    val result = chain.proceed(chain.request())
    result.view()?.let {
      if (it !is ViewGroup) {
        val drawable = ShapeDrawable(RectShape())
        drawable.paint.style = Style.STROKE
        drawable.paint.color = ColorUtils.setAlphaComponent(Color.RED, 190)
        drawable.paint.strokeWidth = 2 * it.resources.displayMetrics.density

        it.viewTreeObserver.addOnPreDrawListener {
          drawable.setBounds(0, 0, it.width, it.height)
          it.overlay.clear()
          it.overlay.add(drawable)
          true
        }
      }
    }
    return result
  }
}

Swap out Assets or Views

The android-geocities-theme library makes use of ViewPump to update the images that are set in ImageViews, blink & scroll text in TextViews, and change the background of the ContentFrameLayout.

Update Hardcoded Strings with New Text

Philology uses ViewPump to intercept the view inflation process and reword string resources to dynamically replace strings of your app or provide translations for new languages over-the-air without needing to publish a new release on Google Play.