Comments (13)
Could you provide some sample code of how you're creating the views?
Note that views should be created using the Activity
context which contains the proper theme, and when not created from XML you should pass the proper defStyleAttr
to the View's constructor (e.g. android.R.attr.textViewStyle
for TextView
).
Whether or not setContentView
is used should not play any role here.
from acorn.
Views are created using ViewProvidingScene
's createViewController
parent context parameter. The colors were not inherited like colorPrimary
when Acorn was used. But setting the view directly to setContentView
it got the right colors.
from acorn.
Are you using AcornAppCompatActivity
?
from acorn.
Yes, and I am relying to the colorPrimary
etc.
from acorn.
Hm, this should work actually. The parent: ViewGroup
provided in ViewProvidingScene
is derived from the FrameLayout
provided by the system through android.R.id.content
, which obviously contains the theme info as necessary.
Activity.setContentView
delegates to PhoneWindow.setContentView
, which uses the same Activity context
instance as provided through the parent
instance, so there's no further magic happening there to make themes work.
Without a reproducible example there's not really much to go on from here. Would it be possible to create a sample project that consistently reproduces the issue?
from acorn.
class MainActivity : AcornAppCompatActivity() {
override fun provideNavigatorProvider(): NavigatorProvider {
return DemoNavigatorProvider
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(HomeView(this, DemoModel.values().toList()))
}
}
The whole code is here https://github.com/gumil/acorn-demo
from acorn.
Thanks! That should help a lot.
from acorn.
The issue is more easily reproduced like so:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(TextView(this).apply { text = "HELLO WORLD" })
setContentView(TextView(findViewById<ViewGroup>(R.id.content).context).apply { text = "HELLO WORLD" })
}
}
The assumption I made earlier is that the Context
passed was the same instance in both cases seems to be wrong: the second instance (from the android.R.id.content
View) is a ContextThemeWrapper
.
The baseContext
of this wrapper is in fact the MainActivity
instance, so this 'fixes' the theming issue again:
val context = (findViewById<ViewGroup>(R.id.content).context as ContextThemeWrapper).baseContext
setContentView(TextView(context).apply { text = "HELLO WORLD" })
from acorn.
It seems AppCompat does some hacky things under the hood, by removing the android.R.id.content
id from the original View and applying it to its own view:
// Change our content FrameLayout to use the android.R.id.content id.
// Useful for fragments.
decorContent.setId(View.NO_ID);
abcContent.setId(android.R.id.content);
This abcContent
View is created using an 'emulated' ContextThemeWrapper
:
/**
--
* This needs some explanation. As we can not use the android:theme attribute
* pre-L, we emulate it by manually creating a LayoutInflater using a
* ContextThemeWrapper pointing to actionBarTheme.
*/
TypedValue outValue = new TypedValue();
mContext.getTheme().resolveAttribute(R.attr.actionBarTheme, outValue, true);
themedContext = new ContextThemeWrapper(mContext, outValue.resourceId);
This ContextThemeWrapper
is the instance we're seeing in our issue here, which resolves to the ActionBarTheme
and not the app's theme..
I'm not sure yet why LayoutInflater.from
that ContextThemeWrapper
uses proper theming though (which is why I haven't seen this issue before).
from acorn.
A quick-and-dirty fix could be to insert a FrameLayout
in between with the proper Context
instance like so:
class MainActivity : AcornAppCompatActivity() {
private lateinit var rootView: ViewGroup
override fun onCreate(savedInstanceState: Bundle?) {
rootView = FrameLayout(this)
setContentView(rootView)
super.onCreate(savedInstanceState)
}
override fun provideNavigatorProvider(): NavigatorProvider {
return DemoNavigatorProvider
}
override fun provideRootView(): ViewGroup {
return rootView
}
}
I'll see and find if there's a 'proper' fix for this, or if something like this will be included in AcornAppCompatActivity
.
from acorn.
Thank you for further investigating this!
I think this workaround works. Seems also like an edge case since I am just experimenting on Acorn
and programmatic views with Contour
. I just have this idea that when Jetpack Compose
is released, programmatic views will be more common.
from acorn.
Yeah it's a basic case that really should work though. Thanks again for the repro!
from acorn.
An investigative issue on the android tracker: https://issuetracker.google.com/issues/141726320
from acorn.
Related Issues (20)
- Compile time issue HOT 9
- Reconsider Kotlin Android Extensions usage
- CircleCI builds fail due to memory issues
- BindingSceneTransitionFactory wrongly falls back to defaults
- Don't remove view on push HOT 14
- API 21 requirement? HOT 3
- Using Dagger to constructor inject Scenes that also receive saved state HOT 4
- No way to know if Transitions to same Scene class is backwards HOT 3
- Arrow Dependency in acorn-ext module HOT 1
- Lint check for providing savedstate without implementing SavableX
- Integration with unidirectional/mvi architecture HOT 5
- Gradle dependency issue in java module HOT 4
- Press back twice to close the activity HOT 9
- ViewController reacts to the scene transition ends
- [BUG] Strange scene lifecycle using an ActivityController HOT 7
- Abstraction of AcornActivities to handle Jetpack Compose HOT 1
- Intercepts the controller view when it's immediately added to the root ViewGroup HOT 1
- Root navigator is not destroyed
- Use of mutation testing in acorn - Help needed HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from acorn.