Make Two Views Share Click Feedback in Constraint Layout - android-layout

I have this situation where I have a constraint layout. Within it lies two views. An ImageView and a TextView. When either of these Views is clicked, I want both to produce a feedback (text color change for textview and drawable tint in imageview) but I can't seem to think of a way to do these unless I put them inside another viewgroup.
Can someone show me how this could be done in constraint Layout? thank you.

Take a look at performClick().
performClick
boolean performClick ()
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
The idea is that when one view is clicked, your code will call performClick() on the other view. You will have to make sure that you inhibit any duplication of actions if the two views do the same function.
Other than doing this in code, I don't know of a way using just XML. There is the concept of a Group in ConstraintLayout but that just a way to control the visibility of the members of the group and does not extend to other properties.
I would use another enclosing view group unless you have a requirement not to. I just seems easier.

Use Group concept in ConstraintLayout refer: https://developer.android.com/reference/android/support/constraint/Group ,https://riggaroo.co.za/constraintlayout-guidelines-barriers-chains-groups/ ,
in java
Group group = findViewById(R.id.group);
int refIds[] = group.getReferencedIds();
for (int id : refIds) {
findViewById(id).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// your code here.
}
});
}
Kotlin:
fun Group.setAllOnClickListener(listener: View.OnClickListener?) {
referencedIds.forEach { id ->
rootView.findViewById<View>(id).setOnClickListener(listener)
}
}
Then call the function on the group:
group.setAllOnClickListener(View.OnClickListener {
// your code here.
})

Related

SwiftUI ColorPicker "opened" and "closed" events?

I need to be able to undo / redo the colors that are picked with the new SwiftUI ColorPicker ( on the iPad : it's presented as a floating window )
The thing that makes it very difficult is that there is apparently no way to know that the user has indeed chosen a color ( and therefore closed the panel )
Instead, the behavior of ColorPicker is that it will keep updating the binded color as the user is manipulating the color controls. This is very helpful to show a live preview, but you don't want to register all these color variations for undo / redo purposes : you only want the color that was finally picked.
Therefore there is no logical distinction between the colors that the user tried, and the one that was selected
And I looked everywhere : there aren't any modifiers / notifications related to that.
I know SwiftUI hasn't been there for long, but this seems like a crucial functionality that's missing?
Has anyone found a workaround?
Undo is always tricky. One size does not fit all. In this case a good solution is to throttle the number of events that come into the UndoManager. You can do so by comparing the current time to the time you last commit.
Create a view model that represents your Source of Truth, and conform to ObservableObject to publish events. It will own the UndoManager. It will have a computed property that gets/sets to the internal data, and check the current time against the time of last commit.
class EditViewModel: ObservableObject {
var commitTime = Date.now
let undoManager = UndoManager()
private var _color: Color = .red {
didSet {
objectWillChange.send()
}
}
var color: Color {
get { _color }
set {
let oldValue = color
let now = Date.now
if now.timeIntervalSince(commitTime) > 1 {
undoManager.registerUndo(withTarget: self) {
$0.color = oldValue
}
}
self.commitTime = now
_color = newValue
}
}
}
Now all that's left to do is create your view and pass in the binding. The implementation details are opaque to the View since it is managed by the ViewModel.
struct EditView: View {
#StateObject var vm = EditViewModel()
var body: some View {
Form {
ColorPicker("Color", selection: $vm.color)
}
}
}
If you need even more control, you can additionally compare the last committed color to the new value and only commit if there is a significant change.
I will also agree that a data-driven approach like SwiftUI's can make undo more tricky. For example, when you need to coalesce multiple operations together into one undo group. By its very nature an undo group is procedural-- the user did one thing after the other, and finally terminates on some condition. But I'm sure there is some way to encapsulate this step-wise operation in a transaction object of some kind.
Undo is hard!

Is it possible to recolor a lottie animation programmatically?

If I have a lottie animation in the form of a json file, is there a way to recolor it in code or even within the json itself?
(To be clear, I hope there's a way to do it without involving After Effects. For instance if I decide to change my app's primary color, the whole app will change except the animation unless there's a way to do that.)
I figured it out. For this example, let's say I want to recolor a specific layer to Color.RED.
You'll need your LottieAnimationView, a KeyPath, and a LottieValueCallback
private LottieAnimationView lottieAnimationVIew;
private KeyPath mKeyPath;
private LottieValueCallback<Integer> mCallback;
Then in your onCreate (or onViewCreated for a fragment) you'll get the animation with findViewById, as well as "addLottieOnCompositionLoadedListener" to the lottieAnimationView, in which you will setup the "mKeyPath" and "mCallback":
lottieAnimationVIew = findViewById(R.id.animationView);
lottieAnimationView.addLottieOnCompositionLoadedListener(new LottieOnCompositionLoadedListener() {
#Override
public void onCompositionLoaded(LottieComposition composition) {
mKeyPath = getKeyPath(); // This is your own method for getting the KeyPath you desire. More on that below.
mCallback = new LottieValueCallback<>();
mCallback.setValue(Color.RED);
checkBox.addValueCallback(mKeyPath, LottieProperty.COLOR, mCallback);
}
});
The argument "LottieProperty.COLOR" specifies which property I am changing.
There's probably a better way to do this, but here's my "getKeyPath" method for finding the specific thing I want to change. It will log every KeyPath so you can see which one you want. Then it returns it once you've supplied the correct index. I saw that the one I want is the 5th in the list, hence the hard-coded index of 4.
private KeyPath getKeyPath() {
List<KeyPath> keyPaths = lottieAnimationView.resolveKeyPath(new KeyPath("Fill", "Ellipse 1", "Fill 1"));
for (int i = 0; i < keyPaths.size(); i++) {
Log.i("KeyPath", keyPaths.get(i).toString());
}
if (keyPaths.size() == 5) {
return keyPaths.get(4);
}
else {
return null;
}
}
Note that the "Fill", "Ellipse 1", "Fill 1" are strings I supplied to narrow the list down to just the ones that have those keys, because I know that the layer I want will be among those. There's likely a better way to do this as well.
There is another thread on this topic with the same approach but a bit simplified:
How to add a color overlay to an animation in Lottie?
Here's directly an example (Kotlin):
yourLottieAnimation.addValueCallback(
KeyPath("whatever_keypath", "**"),
LottieProperty.COLOR_FILTER
) {
PorterDuffColorFilter(
Color.CYAN,
PorterDuff.Mode.SRC_ATOP
)
}
You can find the names of the keypaths also in the Lottie editor.

Orchard CMS front-end all possible content filtering by user permissions

Good day!
In my Orchard, I have several content types all with my custom part attached. This part defines to what users this content is available. For each logged user there is external service, which defines what content user can or cannot access. Now I need access restriction to apply everywhere where orchard display content lists, this includes results by specific tag from a tag cloud, or results listed from Taxonomy term. I seems can’t find any good way to do it except modifying TaxonomyServices code as well as TagCloud services, to join also my part and filter by it. Is this indeed the only way to do it or there are other solutions? I would like to avoid doing changes to built-in modules if possible but cannot find other way.
Thanks in advance.
I'm currently bumbling around with the same issue. One way I'm currently looking at is to hook into the content manager.
[OrchardSuppressDependency("Orchard.ContentManagement.DefaultContentManager")]
public class ModContentManager : DefaultContentManager, IContentManager
{
//private readonly Lazy<IShapeFactory> _shapeFactory;
private readonly IModAuthContext _modAuthContext;
public ModContentManager(IComponentContext context,
IRepository<ContentTypeRecord> contentTypeRepository,
IRepository<ContentItemRecord> contentItemRepository,
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
IContentDefinitionManager contentDefinitionManager,
ICacheManager cacheManager,
Func<IContentManagerSession> contentManagerSession,
Lazy<IContentDisplay> contentDisplay,
Lazy<ISessionLocator> sessionLocator,
Lazy<IEnumerable<IContentHandler>> handlers,
Lazy<IEnumerable<IIdentityResolverSelector>> identityResolverSelectors,
Lazy<IEnumerable<ISqlStatementProvider>> sqlStatementProviders,
ShellSettings shellSettings,
ISignals signals,
//Lazy<IShapeFactory> shapeFactory,
IModAuthContext modAuthContext)
: base(context,
contentTypeRepository,
contentItemRepository,
contentItemVersionRepository,
contentDefinitionManager,
cacheManager,
contentManagerSession,
contentDisplay,
sessionLocator,
handlers,
identityResolverSelectors,
sqlStatementProviders,
shellSettings,
signals) {
//_shapeFactory = shapeFactory;
_modAuthContext = modAuthContext;
}
public new dynamic BuildDisplay(IContent content, string displayType = "", string groupId = "") {
// So you could do something like...
// var myPart = content.As<MyAuthoPart>();
// if(!myPart.IsUserAuthorized)...
// then display something else or display nothing (I think returning null works for this but
//don't quote me on that. Can always return a random empty shape)
// else return base.BuildDisplay(content, displayType, groupId);
// ever want to display a shape based on the name...
//dynamic shapes = _shapeFactory.Value;
}
}
}
Could also hook into the IAuthorizationServiceEventHandler, which is activated before in the main ItemController and do a check to see if you are rendering a projection or taxonomy list set a value to tell your content manager to perform checks else just let them through. Might help :)

EXT.Net - Dynamic UserControlLoader with Property

I need a solution to the below scenario. I'm developing an application in ASP.Net with the help of EXT.Net Controls.
In my scenario, I'm creating dynamic tabs (EXT.Net) and loading an User Control dynamically with UserControlLoader component.
How can I pass a parameter to the UserControl dynamically? Below is my sample code.
[DirectMethod]
public void AddNewTab()
{
getTitle gt = new getTitle();
Ext.Net.Panel panel = new Ext.Net.Panel
{
Title = gt.Title(),
Closable = false,
Layout = "Fit",
Items = {
new UserControlLoader{
Path="ElementChooser.ascx"
}
}
};
TabPanel1.Add(panel);
panel.Render();
TabPanel1.SetLastTabAsActive();
}
Your help is highly appreciated.
It is a bit unclear what "pass a parameter to a User Control" means, but I think you need to handle the UserControlLoader's OnUserControlAdded and OnComponentAdded events.
The first one fires when a user control is added to a UserControlLoader.
The second one fires for each top level Ext.NET component from a user control.
These events helps to configure a user control and its components as needed.
Here is an example with the OnComponentAdded example.

Check if form is changed in ext-gwt and highlight save button

this might be a simple question.
we have a form with different widgets, tables and etc.
in that form we need to highlight save button and enable/disable other action buttons
right after a user changed form data.
do you know about any elegant way to handle dirty forms
I like http://plugins.jquery.com/project/dirtyform but this is not gxt.
Thank you,
SLava
If you are using FormBindings and BeanModel then just implement a changeListener to your BeanModel and do what you need to in that method.
For example:
myBean= BeanModelLookup.get().getFactory(MyBean.class)
.createModel(myBean);
myBean.addChangeListener(new ChangeListener() {
public void modelChanged(ChangeEvent event) {
PropertyChangeEvent propertyEvent = (PropertyChangeEvent) event;
if (!propertyEvent.getOldValue().toString().equals(
propertyEvent.getNewValue().toString())) {
hasBeanChanged= true;
}
}
});

Resources