macroid icon indicating copy to clipboard operation
macroid copied to clipboard

enhancement: access to layoutparams after lp tweak

Open pfn opened this issue 11 years ago • 12 comments

many layout params require field changes instead of only constructor parameters (e.g. gravity, span, relative layout stuff, etc. [yes, there's RuleRelativeLayout, but that's besides the point]).

I don't have a good solution for this yet, but maybe something like an optional parameter set, e.g.

lp[A](...)(Map(field -> value))

or

lp[A](...) { p: A.LayoutParams(????) => p.... } // I don't see how this is possible

Alternatively, figure out a good way of creating AttributeSets so that one can do lp[A](Map(...).toAttributeSet)

etc.

pfn avatar Aug 15 '14 17:08 pfn

setting layout margins is definitely a pain point

currently I have to run: lp + margins

where margins is something ugly like tweak { v: View => v.getLayoutParams.asIntanceOf[ViewGroup.MarginLayoutParams] ...}

and it requires having set lp beforehand

pfn avatar Aug 15 '14 17:08 pfn

Yeah, I actually avoid using margins, replacing them with padding where possible :) From your suggestions, I think AttributeSets are the way to go, as it will also solve #30. Unfortunately, I don’t have any time to work on this now. Would you or @dant3 be interested in looking into AttributeSet stuff?

stanch avatar Aug 15 '14 22:08 stanch

After some experiments with macroid, I too feel lp as a pain point (if not using xml layouts :stuck_out_tongue:). AttributeSet api is definitely way to go to solve this, and similar issues. Not sure if I have enough time currently, but I could look at it later, if nobody will pick it up before.

dant3 avatar Aug 16 '14 21:08 dant3

@dant3 I think we can agree that Android’s LayoutParams API itself is a bit of a mess ;)

stanch avatar Aug 17 '14 10:08 stanch

By the way, how much is it desired to change layout params after layout? If they are only set once, maybe widgets could be wrapped into something like this before being added to the layout:

// isParams is generated by an implicit macro
case class LP[L <: ViewGroup, +W <: View, X](view: W, params: X)(implicit isParams: IsParams[X, L])

I guess this could offer more type safety if done right, but not sure about the details yet. What do you think?

stanch avatar Aug 17 '14 10:08 stanch

I don't understand how this would streamline the lp generation?

isParams only links VG and VG.LP?

Sent from my phone On Aug 17, 2014 3:38 AM, "Nick" [email protected] wrote:

By the way, how much is it desired to change layout params after layout? If they are only set once, maybe widgets could be wrapped into something like this before being added to the layout:

// isParams is generated by an implicit macrocase class LP[L <: ViewGroup, +W <: View, X](view: W, params: X)(implicit isParams: IsParams[X, L])

I guess this could offer more type safety if done right, but not sure about the details yet. What do you think?

— Reply to this email directly or view it on GitHub https://github.com/macroid/macroid/issues/34#issuecomment-52418618.

pfn avatar Aug 17 '14 18:08 pfn

Oh, I suppose the case class can take a function to operate on the params.

Rather than params: X it should be params: (X => Unit)?

pfn avatar Aug 17 '14 18:08 pfn

Also, interestingly, it'd be nice if WindowManager.LayoutParams could be supported as well. It isn't a view group... But one applies the layout params to content views..

pfn avatar Aug 17 '14 18:08 pfn

Sorry for not being elaborate enough. To give an example, if we wanted to add a Button to a LinearLayout, we would wrap it into

LP[LinearLayout, Button, LinearLayout.LayoutParams](w[Button], new LinearLayout.LayoutParams(...))

although your idea with X ⇒ Unit works as well. The way isParams works is that there will be automatic implicits for these relations:

implicitly[IsParams[LinearLayout.LayoutParams, LinearLayout]]
implicitly[IsParams[ViewGroup.LayoutParams, LinearLayout]]
...

Does this make sense?

To deal with WindowManager.LayoutParams, we could provide an alternative version of setContentView (also see #22) that takes something like Ui[LP[View]] (LP will need to drop the L <: ViewGroup restriction).

stanch avatar Aug 17 '14 19:08 stanch

I don’t understand how this would streamline the lp generation?

Oh well, this is somewhat orthogonal, but I thought extra type safety might help to deal with this horrible API. As far as configuring the actual params is concerned, AttributeSet still seems the way to go.

stanch avatar Aug 17 '14 19:08 stanch

This is basically what I came up with for my own thing.

  abstract class LpRelation[V <: ViewGroup, LP <: ViewGroup.LayoutParams : ClassTag] {
    def lpType = implicitly[ClassTag[LP]].runtimeClass
    def lp(args: Any*) = lpType.getConstructor(
      args map { a =>
        val c = a.getClass
        primitiveMap.getOrElse(c, c)
      }:_*).newInstance(args map (_.asInstanceOf[AnyRef]): _*).asInstanceOf[LP]
  }
  implicit object LLRelation extends LpRelation[LinearLayout, LinearLayout.LayoutParams]
  implicit object TRRelation extends LpRelation[TableRow, TableRow.LayoutParams]

pfn avatar Aug 18 '14 20:08 pfn

Oh, can't forget the rest.

  def lp2[V <: ViewGroup,LP <: ViewGroup.LayoutParams, C](args: Any*)
                                                         (p: LP => C)
                                                         (implicit r: LpRelation[V,LP]) = tweak {
    v: View =>
      val lp = r.lp(args: _*)
      p(lp)
      v.setLayoutParams(lp)
  }

pfn avatar Aug 18 '14 20:08 pfn