Explanation of Problem:
New beginner in iOS SwiftUI here! I am currently building a list with a toggle and some text.
Unfortunately each time the toggle has its binary value changed - the list flashes briefly. How do I solve this issue?
Animated Screenshot:
Current SwiftUI Code:
ForEach(models, id: \.self)
{ model in
VStack(alignment: .leading, spacing: 1)
{
Toggle("Lorem ipsum dolor sit amet", isOn: model.enabled.didSet
{ isOn in
model.doSomeLogicWithThis(enabled: isOn)
})
if model.hasDescr
{
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.").multilineTextAlignment(.leading).foregroundColor(.gray).font(.footnote)
}
}
}
Related
I have a multiline text with info button at the end of the text which is done with HStack at the moment.
HStack(spacing: 15) {
Image(uiImage: "questionMark")
.resizable()
.scaledToFit()
.frame(width: 15, height: 15)
Text("Neque porro quisquam est qui dolorem ipsum quia dolor sit amet.")
.fixedSize(horizontal: false, vertical: true)
}
which looks like this:
Goal:
But I want to have the button at the end of the last text like infoIcon should appear right after ipsum.
Note:
What could be the best solution to achieve this and would like not to use UIKit in this regards?
The possible solution is to add use Image constructor of Text but you can not add action only the image.
Like this
struct ContentView: View {
var body: some View {
fullImageText
.onTapGesture {
}
}
var fullImageText: Text {
Text("Neque porro quisquam est qui dolorem ipsum quia dolor sit amet.") + Text(Image("edit"))
}
}
Another solution is to use NSMutableAttributedString wrap with UIViewRepresentable. Here is demo : https://stackoverflow.com/a/62169577/14733292
I have a ScrollView in SwiftUI with multiple elements, some of them expands on tap.
struct ExpandingView: View {
#State var showContent = false
var body: some View {
VStack {
HStack {
Button(action: {withAnimation {
self.showContent.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
}
Text("TITLE")
.padding(.leading, 10)
Spacer()
}
if showContent {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
}
}
}
}
struct Test: View {
var body: some View {
ScrollView {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}
}
}
If you try to open one of the expanding texts, you will see that the transition is not smooth, it kind of like jumps and then the transition starts.
So here is what I've tried:
If I remove the scrollview and put this to VStack for example it is working fine, but that is not an option because I have much more elements which will not fit on the screen.
I've tried to set an animation for the scrollview because I read that it solves this kind of problem, like this:
ScrollView {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}.animation(.spring())
It works fine in terms of the opening transition, it even looks better with the spring effect, but the spring animation for the whole scrollview plays when the view appears, which I don't want.
Again, if I change the ScrollView to a VStack, the animation does not play on appearing which is nice, but I have to use a scrollview. So the best solution for me would be to keep the animation for opening the texts, but somehow remove it when the view appears.
Here is possible solution. Read also comments inline. Tested with Xcode 11.4 / iSO 13.4
struct ExpandingView: View {
#State var showContent = false
var body: some View {
VStack {
HStack {
Button(action: {
self.showContent.toggle()
}) {
Image(systemName: "chevron.right.circle")
}
Text("TITLE")
.padding(.leading, 10)
Spacer()
}
if showContent {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras volutpat dapibus ante eget laoreet. Aenean lacus elit, auctor ut nisl id, fermentum pretium mi. Quisque lacus nisl, suscipit hendrerit est sed, congue dictum augue. Suspendisse semper viverra accumsan. Maecenas commodo turpis convallis nisl bibendum pharetra.")
.fixedSize(horizontal: false, vertical: true)
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
}
}
}
}
struct DemoExpandingView: View {
// initial nil to avoid initial animation
#State private var animation: Animation? = nil
var body: some View {
ScrollView {
VStack {
ExpandingView()
ExpandingView()
ExpandingView()
Text("Some static text")
}.animation(animation) // << needed to animate static section
}
.onAppear {
DispatchQueue.main.async {
// assign in-container animation `after` container rendered
self.animation = .default
}
}
}
}
How can I have a different Text when a Element is selected then what is displayed yet.
Background: The Text I display for in the Option is pretty long, so I want to show a shorter version, when it is slected.
You can use the templateSelection option of Select2 with some custom attribute to option tag
HTML:
<select id="long" class="js-example-basic-multiple" multiple="multiple">
<option data-custom="" value="all">All </option>
<option data-custom="Lorem ipsum" value="#FF0000">Lorem ipsum dolor sit amet consectetur adipiscing elit</option>
<option data-custom="Sed do" value="#00FF00">Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</option>
<option data-custom="Ut enim" value="#0000FF">Ut enim ad minim veniam quis nostrud exercitation</option>
<option data-custom="Duis aute" value="#FFFF00">Duis aute irure dolor in reprehenderit in voluptate velit esse</option>
</select>
Javascript:
jQuery(function() {
jQuery('#long').select2({
templateSelection: function (selection) {
return jQuery(selection.element).data('custom');
}
});
});
https://jsfiddle.net/rijokpaul/phz9e5cs/4/
im trying to restrict 120 characters to be displayed.while the rest should be represented as "(more..)".which is make clickable to view the entire content.when i enter desc with space..the "(more..)" moves to the second..if i dont use space...it moves to the first line.
<h:outputScript>interaction360();
function interaction360(){
$(document).ready(function(){
var maxLength = 120;
$(".show-read-more").each(function(){
var myStr = $(this).text();
if($.trim(myStr).length > maxLength){
var newStr = myStr.substring(0, maxLength);
var removedStr = myStr.substring(maxLength, $.trim(myStr).length);
$(this).empty().html(newStr);
$(this).append('<span class="more-text"> (more...) </span>');
}
});
$(".more-text").css("color","blue");
});
}
Live Demo Link : CodePen
HTML code :
<span class="more">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</span>
CSS Code :
.morecontent span { display: none; }
.morelink { display: block; }
jQuery Code:
$(document).ready(function() {
// Configure/customize these variables.
var showChar = 120; // How many characters are shown by default
var ellipsestext = "...";
var moretext = "Show more ...";
var lesstext = "Show less";
$('.more').each(function() {
var content = $(this).html();
if(content.length > showChar) {
var c = content.substr(0, showChar);
var h = content.substr(showChar, content.length - showChar);
var html = c + '<span class="moreellipses">' + ellipsestext+ ' </span><span class="morecontent"><span>' + h + '</span> ' + moretext + '</span>';
$(this).html(html);
}
});
$(".morelink").click(function(){
if($(this).hasClass("less")) {
$(this).removeClass("less");
$(this).html(moretext);
} else {
$(this).addClass("less");
$(this).html(lesstext);
}
$(this).parent().prev().toggle();
$(this).prev().toggle();
return false;
});
});
Hope it will work for you.
For the problem I'm trying to solve, I have a table with unique content for each row. The rows are allowed to be reordered via a handle, and the content of each row is not always of uniform height. Sometimes large amounts of text and / or images appear within a row.
There can also be multiple tables with rows that can be reordered, so I'm using the containment property to prevent dragging into other zones and other problematic issues that occur when dragging outside the desired area.
The problem is when I attempt to drag a "tall" row to the top or bottom of the order when the top and bottom are "short" by comparison. Essentially I am not allowed to drag tall rows to the these positions. I have searched for a solution and have come up short. Any help would be appreciated.
Working example here: http://jsfiddle.net/jeffvoigt/XyPzf/
Neither of the two middle rows can be dragged to the top or bottom of the list.
HTML:
<div class="container">
<table id="sortable">
<tr class="odd">
<td><p>[=]</p></td>
<td>Single Line of Text</td>
</tr>
<tr class="even">
<td><p>[=]</p></td>
<td>Aenean porta, tellus quis auctor elementum, risus ante ornare augue, eu elementum nunc libero ut nisi. Pellentesque sed vestibulum tellus. Proin convallis enim eget felis iaculis viverra vestibulum lorem semper. Aliquam imperdiet viverra lorem, ut dignissim felis laoreet vel. Suspendisse fermentum neque eu est vestibulum bibendum. Maecenas dignissim egestas tempor. Ut tincidunt metus sed felis ornare nec sollicitudin risus gravida. Duis vitae mauris quis risus ultricies malesuada. Nulla facilisi. Phasellus fringilla, arcu eget congue sollicitudin, lorem elit ullamcorper ante, non fermentum orci mauris at tellus. Maecenas suscipit sodales molestie. Mauris luctus porta dui non volutpat.</td>
</tr>
<tr class="odd">
<td><p>[=]</p></td>
<td><img src="http://www.google.com/intl/en_ALL/images/logos/images_logo_lg.gif" /></td>
</tr>
<tr class="even">
<td><p>[=]</p></td>
<td>Single Line of Text</td>
</tr>
</table>
</div>
Javascript:
$( "#sortable tbody" ).sortable({
axis: "y",
containment: ".container",
cursor: "move",
handle: "p"
});
I faced the same issue. This is the quick solution:
$('.collections').sortable({
handle: 'h3',
axis: 'y',
containment: 'parent',
items: '.collection',
cursor: 'move',
tolerance: 'pointer',
scroll: true,
beforeStop: function(event, ui) {
var lastElemTop = $('.collections .collection:last-child').position().top;
var currElemTop = ui.position.top;
var currElemHeight = ui.item.height();
if (currElemTop + currElemHeight * 2 > lastElemTop) {
$('.collections .collection:last-child').insertBefore(ui.item);
}
}
});
The problem is the placement of your handle determines the Y position of the sort in relation to the handle it is on top of. So, to demonstrate, go to jsFiddle and add a valign=top to your big text area. The handle moves to the top of the sortable element, and when you drag it to the top where the short line of text is it will snap into place, but you cannot get it to sort to the bottom. However, if you update the fiddle to be valign=bottom, you may snap it to the bottom but not the top.
Solutions would be to either make your entire content area a sortable handle or perhaps move your handles out to the left of the content (making that the 'sortable' area only) and drag only the handles (not the content), then allow the the content area to update upon a new sort.
Basically, it needs to be some how re-envisioned or designed to function properly.
I encountered this very same problem. It seems like this only happens when there is no content or spacing beneath the jQuery Sortable list.
Just adding some spacing (e.g. <div id="end-of-page-spacer" style="height: 500px;"></div>) allowed me to drag large rows beneath smaller rows situated at the bottom of the list.