Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

enhancement: access to layoutparams after lp tweak #34

Open
pfn opened this issue Aug 15, 2014 · 12 comments
Open

enhancement: access to layoutparams after lp tweak #34

pfn opened this issue Aug 15, 2014 · 12 comments

Comments

@pfn
Copy link

pfn commented Aug 15, 2014

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
Copy link
Author

pfn commented Aug 15, 2014

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

@stanch
Copy link
Collaborator

stanch commented Aug 15, 2014

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?

@dant3
Copy link

dant3 commented Aug 16, 2014

After some experiments with macroid, I too feel lp as a pain point (if not using xml layouts 😛). 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.

@stanch
Copy link
Collaborator

stanch commented Aug 17, 2014

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

@stanch
Copy link
Collaborator

stanch commented Aug 17, 2014

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?

@pfn
Copy link
Author

pfn commented Aug 17, 2014

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
#34 (comment).

@pfn
Copy link
Author

pfn commented Aug 17, 2014

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
Copy link
Author

pfn commented Aug 17, 2014

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..

@stanch
Copy link
Collaborator

stanch commented Aug 17, 2014

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
Copy link
Collaborator

stanch commented Aug 17, 2014

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.

@pfn
Copy link
Author

pfn commented Aug 18, 2014

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
Copy link
Author

pfn commented Aug 18, 2014

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)
  }

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants