I'm building an EPG layout from scratch and I want to calculate the width of the cells for the programs based on their runtime. I thought the best way to go about this is converting them to pixels and setting the width of the item to that. But it's coming up very small (maybe 5pixels at most). Is there a way to achieve this? Even better if I can use DP instead of PX. Below is the formula I'm using to do the conversion
fun convertMillisecondsToPx(millis: Float, context: Context): Float =
millis * pxPerMinConstant(context) / TimeUnit.MINUTES.toMillis(1)
with pxPerMinConstant(context)
fun pxPerMinConstant(context: Context): Float =
convertDpToPixel(context.resources.getDimension(R.dimen.epg_width_one_min), context)
and convertDpToPixel
fun convertDpToPixel(dp: Float, context: Context): Float =
applyDimension(COMPLEX_UNIT_DIP, dp, context.resources.displayMetrics)
and dimen_epg_width_one_min = 2dp
Related
I have a LinearLayoutCompat that doesn't fit into the screen. So, I decided to implement 'drag to pan' feature for the user to scroll to any part of the layout (in all directions). It's suggested that we should do it like the code snippet on Android's official website:
// The current viewport. This rectangle represents the currently visible
// chart domain and range.
private val mCurrentViewport = RectF(AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX, AXIS_Y_MAX)
// The current destination rectangle (in pixel coordinates) into which the
// chart data should be drawn.
private val mContentRect: Rect? = null
private val mGestureListener = object : GestureDetector.SimpleOnGestureListener() {
...
override fun onScroll(
e1: MotionEvent,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
// Scrolling uses math based on the viewport (as opposed to math using pixels).
mContentRect?.apply {
// Pixel offset is the offset in screen pixels, while viewport offset is the
// offset within the current viewport.
val viewportOffsetX = distanceX * mCurrentViewport.width() / width()
val viewportOffsetY = -distanceY * mCurrentViewport.height() / height()
// Updates the viewport, refreshes the display.
setViewportBottomLeft(
mCurrentViewport.left + viewportOffsetX,
mCurrentViewport.bottom + viewportOffsetY
)
}
return true
}
}
The problem is I don't understand what the mCurrentViewPort variable is and how I should obtain the values for AXIS_X_MIN, AXIS_Y_MIN, AXIS_X_MAX and AXIS_Y_MAX to pass to the RecF object. Also, setViewPortBottomLeft(...) is marked as unresolved reference for me.
This question already has answers here:
How to convert DP, PX, SP among each other, especially DP and SP?
(6 answers)
Closed 2 years ago.
I have a custom class to use offsets inside my RecyclerView.
class SpacesItemDecoration(private var space: Int) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
super.getItemOffsets(outRect, view, parent, state)
outRect.bottom = space
}
}
Then I set the offsets in my code like that:
addItemDecoration(SpacesItemDecoration(25))
It works, but it sets the offsets in pixels. How am I supposed to use dp instead of pixels? And why Google preferred using pixels here? It already should be deprecated.
by this method you should first convert dp to pixels than set
fun Context.dpToPixel(dp: Float): Float {
return dp * (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
by this
addItemDecoration(SpacesItemDecoration(dpToPixel(25f)))
I can't change the value of an initialised variable.
I tried googling the problem to no avail.
Float is a primitive type so it cannot be lateinit.
class RegistrationActivity : AppCompatActivity() {
val scale = 0f
public override fun onStart() {
super.onStart()
scale = this.resources.displayMetrics.density
}
}
I expect to be able to initialise the "scale" variable outside of a method body so that it can be used by other methods, but in my attempt I'm met with the "Val cannot be reassigned" as an error inside of the "onStart()" method when I hover over "scale" in "scale = this.resources.displayMetrics.density".
You need to use
var scale = 0f
instead of
val scale = 0f
val is immutable and it can not change over the time
var can change over the time
If you came from java.
val scale = 0f will be the equivalent for
final float scale = 0f;
Following Jama Matrices are defined in my code:
P: 3*3 Matrix
I: 3*3 identity Matrix
K: 3*2 Matrix
H: 2*3 Matrix
Q: 3*3 Matrix
Following is my code snippet:
private Matrix getP() {
P= (I.minus(K.times(H))).times(Q);
Log.d("csv", "P is calculated");
return P;
}
While running the code, at first iteration it works, i.e, P is calculated is printed at the Logcat. However, it happens only once and the application gets stopped. Following is the error:
java.lang.IllegalArgumentException: Matrix inner dimensions must agree.
If the Matrix inner dimension was the error, how come it runs for the first iteration? I obtained some information about the inner dimension at this link. However, I could not figure out the solution. When the equation is manually checked, the matrix dimension matches.
Anything wrong with my approach??
Thank you.
Do you mind showing how you are calling getP? The following works no matter how many times I click on the fab button.
class MainActivity : AppCompatActivity() {
val I = Matrix.identity(3,3)
val K = Matrix(3,2,5.0)
val H = Matrix(2,3,7.0)
val Q = Matrix(3,3,8.0)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fab.setOnClickListener { view ->
getP()
}
}
private fun getP():Matrix{
val P = (I.minus(K.times(H))).times(Q)
Log.d("MainActivity","P is calculated")
return P
}
}
When getP returns where are you storing the results? Are you possibly overwriting one of the matrices?
Update
If your situation is such that making the variables final is not an option for you, then you can log each matrix's dimension and then debug the one that changes.
private fun getP():Matrix{
Log.d(TAG,"I dimension: ${I.rowDimension} x ${I.columnDimension}")
Log.d(TAG,"K dimension: ${K.rowDimension} x ${K.columnDimension}")
Log.d(TAG,"H dimension: ${H.rowDimension} x ${H.columnDimension}")
Log.d(TAG,"Q dimension: ${Q.rowDimension} x ${Q.columnDimension}")
val P = (I.minus(K.times(H))).times(Q)
Log.d(TAG,"P is calculated")
return P
}
I have two packages with one that is the primary package with the MainActivity. The other package gets imported into the MainActivity. The other package deals with drawing on a canvas. However, any changes that I am making to the imported package are not showing up on the actual app. For example, when i change the size of the rectangle being drawn, nothing is actually changing. Does anyone know why this is?
Sorry if this is a trivial question, I just started learning android dev. Also, I got the code off of github, and i'm trying to learn from it. If there is any information that I left out that is crucial please ask. Thank
The code is from: https://github.com/husaynhakeem/android-face-detector
The specific part that I had tried to change is the ANCHOR_RADIUS, ID_OFFSET, as well as the xOffset, yOffset values in the FaceBoundsOverlay. Each variable affects some boundary that is supposed to be used to draw the rectangle and center dot. I pasted the drawAnchor method down below. In that method, when I changed the ANCHOR_RADIUS to 50f, I expected the dot to become larger but nothing was changed.
The FaceBoundsOverlay is in the package called facedetector while the MainActivity is in the package called facedetectorapp
class FaceBoundsOverlay #JvmOverloads constructor(
ctx: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0) : View(ctx, attrs, defStyleAttr) {
.....
private fun drawAnchor(canvas: Canvas, centerX: Float, centerY:
Float) { private fun drawAnchor(canvas: Canvas, centerX: Float,
centerY: Float) {
canvas.drawCircle(
centerX,
centerY,
ANCHOR_RADIUS,
anchorPaint)
}
companion object {
private const val ANCHOR_RADIUS = 10f
// private const val ANCHOR_RADIUS = 50f
private const val ID_OFFSET = 50f
}
}