Detect when NSScrollView can be scrolled - objective-c

How can I detect when there is more text than is showing in NSScrollView?
I have tried various forms of this:
if (self.scrollView.contentSize.height > self.scrollView.bounds.size.height) {
NSLog (#"Can be scrolled.");
}
".contentSize" and ".bounds" always have the same dimensions.

Related

Why UICollectionView stops working when NSMutableAttributedString is set to one of its cells

I stumbled upon a special problem in my current project.
We have UICollectionView using a custom layout called SquareMosaicLayout.
Within this collection view the first cell it presenting a UITextView.
This text view again shall show an html text created with:
NSMutableAttributedString(fromHTMLString: htmlString, textColor: textColor, font: font)
Now when this string is assigned to the text view the collection view somehow stops working which means it does not ask the datasource for new cells when scrolling through the collection view.
This results in the collection view showing blank space.
Unfortunately I did not have time to isolate the problem in terms of if the custom layout breaks anything but it definitely has to do with assigning the string. If we don't do that the collection view works as expected.
We still did not found the reason for the behaviour but a first workaround.
It is possible to set the NSMutableAttributedString asynchronously.
extension UITextView {
[ ... ]
DispatchQueue.main.async {
let optionalAttributedText = NSMutableAttributedString(fromHTMLString: htmlString, textColor: self.textColor, font: self.font)
guard let attributedText = optionalAttributedText else { return }
self.attributedText = attributedText
[ ... ]
In that case the UICollectionView behaves normal showing all the cells.

animation for zoom in and zoom out in android for imageview

How do i set zoom in and zoom out when click on imageview?I want my program to react when user click on imageview must get large to some extent and can move imageview on that screen and sometime it reduce the size along when it move on touch anywhere on the screen .when click again is go resume original size what do i do?
As far as I know there are two ways.
The first way:
Make a new folder in res called 'anim'. Than make a xml file inside, for example zoomin.xml. Afterwards put the following code inside.
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1"
android:toXScale="5"
android:fromYScale="1"
android:toYScale="5"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true">
</scale>
Make another one for zoom out, but with reversed values.
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="5"
android:toXScale="1"
android:fromYScale="5"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true">
</scale>
You can change the values according to your needs. I think that they are self-explanatory.
And now in your java code.
ImageView imageView = (imageView)findViewById(R.id.yourImageViewId);
Animation zoomin = AnimationUtils.loadAnimation(this, R.anim.zoomin);
Animation zoomout = AnimationUtils.loadAnimation(this, R.anim.zoomout);
imageView.setAnimation(zoomin);
imageView.setAnimation(zoomout);
Now you only need to keep track which is the current state. And for each state execute this lines of codes:
imageView.startAnimation(zoomin);
and
imageView.startAnimation(zoomout);
For example:
imageView.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
if(!pressed) {
v.startAnimation(zoomin);
pressed = !pressed;
} else {
v.startAnimation(zoomout);
pressed = !pressed;
}
}
});
The other way is described here : http://developer.android.com/training/animation/zoom.html.
You can make this by following this guide easily
http://developer.android.com/training/animation/zoom.html
shortly you should use third imageview which is invisible when the user touches any imageview you want, you can display it by using animation in the imageview which is invisible.

UICollectionView with preview and paging enabled

I am trying to imitate what Apple has when showing the search result in the App Store. (reference: http://searchengineland.com/apple-app-search-shows-only-one-result-at-a-time-133818)
It shows like the detailed-application-info in a cards and it is paged. I am stuck at how to make the previous-and-next card shows when one active card in the middle and the scroll view's paging behaviour is still intact.
I have tried using the UICollectionView and set the clipSubviews to NO, hoping that it will show the previous page and the next page, but as soon as the cell goes off-screen, the cell gets hidden (removed from the view hierarchy) and not displayed. I think thats the flyweight pattern of the UICollectionView (the behavior of UICollectionView). Any ideas of what would be possible?
Cheers,
Rendy Pranata
The problem: UICollectionView as a subclass of UIScrollView essentially animates its bounds by a stride of bounds.size. Although this could mean that all you had to do is decrease the bounds while keeping the frame bigger, unfortunately UICollectionView will not render any cells outside its current bounds... destroying your preview effect.
The Solution:
Create a UICollectionView with paging set to NO and with the desired frame.
Create UICollectionViewCells that are smaller than the UICollectionView's frame/bounds. At this stage, a part of the next cell should show in the frame. This should be visible before implementing the other steps below.
Add a collectionView.contentInset.left and right (I assume your layout is horizontal) equal to the contentOffsetValue method (as shown below for simplicity) so as to align the first and last cells to the middle.
Create a UICollectionViewFlowLayout which overrides the method that gives the stopping point like so:
Like so:
-(CGFloat)contentOffsetValue
{
return self.collectionView.bounds.size.width * 0.5f - self.itemSize.width * 0.5f;
}
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
static float EscapeVelocity = 0.5f; // otherwise snap back to the middle
NSArray* layoutAttributesArray = [self layoutAttributesForElementsInRect:self.collectionView.bounds];
if(layoutAttributesArray.count == 0)
return proposedContentOffset;
CGFloat currentBoundsCenterX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width * 0.5f;
UICollectionViewLayoutAttributes* candidateNextLayoutAttributes = layoutAttributesArray.firstObject;
for (UICollectionViewLayoutAttributes* layoutAttributes in layoutAttributesArray)
{
if ((layoutAttributes.representedElementCategory != UICollectionElementCategoryCell) ||
(layoutAttributes == candidateNextLayoutAttributes)) // skip the first comparison
continue;
if(velocity.x > EscapeVelocity || velocity.x < -(EscapeVelocity))
{
if(velocity.x > EscapeVelocity && layoutAttributes.center.x > candidateNextLayoutAttributes.center.x)
{
candidateNextLayoutAttributes = layoutAttributes;
}
else if (velocity.x < -(EscapeVelocity) && layoutAttributes.center.x < candidateNextLayoutAttributes.center.x)
{
candidateNextLayoutAttributes = layoutAttributes;
}
}
else
{
if(fabsf(currentBoundsCenterX - layoutAttributes.center.x) < fabsf(currentBoundsCenterX - candidateNextLayoutAttributes.center.x))
{
candidateNextLayoutAttributes = layoutAttributes;
}
}
}
return CGPointMake(candidateNextLayoutAttributes.center.x - self.collectionView.bounds.size.width * 0.5f, proposedContentOffset.y);
}
I just put together a sample project which shows how you could do this. I created a container view which is 100 points wider than the 320 points for the screen. Then I put a UICollectionView into that container. This offsets everything by 50 points on both sides of the screen.
Then there is a content cell which simply has a background and a label so you can visually identify what is happening. On the left and right there are empty cells. In the viewDidLoad method the content inset is set to negative values on the left and right to make the empty cells now scroll into view. You can adjust the inset to your preference.
This mimics the behavior fairly closely. To get the label below, like in the example you can simply check the contentOffset value to determine which cell is in focus. To do that you'd use the UIScrollViewDelegate which is a part of UICollectionView.
https://github.com/brennanMKE/Interfaces/tree/master/ListView
You'll notice this sample project has 2 collection views. One is a normal horizontal flow layout while the other one which has larger cells is the one which mimics the example you mentioned.

Child QWidget is not painted correctly

I need to show a virtual keyboard when the user selects an input text field in a webpage. This code runs on an set top box.
I am extending the QWebView, which is creating a new keyboard widget as a child.
WebView::WebView(QWidget* parent = 0): QWebView(parent)
{
WebPage *page = new WebPage(this);
this->m_keyboard = new widgetKeyBoard(this, Qt::Window|Qt::CustomizeWindowHint);
this->m_keyboard->createKeyboard();
this->m_keyboard->hide();
connect(this, SIGNAL(launchVirtualKB(WebView *) ), SLOT(launchKeyboard(WebView *)));
}
The widgetKeyBoard is made up of QGridLayout with many children QKeyPushButton.
When I do a show of keyboard, I see the whole keyboard drawn briefly and then overwritten 30% of the keyboard from the below web page (overwritten near the input field). I tried to have my own repaint for webview and mainwindow, but still see that someone else is overwriting.
What could be causing such an issue. I am using QT4.8.

How to toggle visibility of NSSplitView subView + hide Pane Splitter divider?

We have a parent Split view (NSSplitView), and two subviews, Content and SideBar (the sidebar is on the right).
What would be the optimal Cocoa-friendly way to toggle the SideBar view?
I would really love it, if the suggested solution includes animation
I really don't need any suggestions related to external plugins, etc (e.g. BWToolkit)
HINT : I've been trying to do that, but still I had issues hiding the divider of the NSSplitView as well. How could I do it, while hiding it at the same time?
Here's a pretty decent tutorial that shows how to do this: Unraveling the Mysteries of NSSplitView.
Hiding the divider is done in NSSplitView's delegate method splitView:shouldHideDividerAtIndex:.
You will have to animate the frame size change yourself if you don't like the way NSSplitView does it.
Easiest way to do it is as follows - and it's animated: [SWIFT 5]
splitViewItems[1].animator().isCollapsed = true // Show side pane
splitViewItems[1].animator().isCollapsed = false // hide side pane
I wrote a Swift version of the content in the link from #Nathan's answer that works for me. In the context of my example splitView is set elsewhere, probably as an instance property on an encompassing class:
func toggleSidebar () {
if splitView.isSubviewCollapsed(splitView.subviews[1] as NSView) {
openSidebar()
} else {
closeSidebar()
}
}
func closeSidebar () {
let mainView = splitView.subviews[0] as NSView
let sidepanel = splitView.subviews[1] as NSView
sidepanel.hidden = true
let viewFrame = splitView.frame
mainView.frame.size = NSMakeSize(viewFrame.size.width, viewFrame.size.height)
splitView.display()
}
func openSidebar () {
let sidepanel = splitView.subviews[1] as NSView
sidepanel.hidden = false
let viewFrame = splitView.frame
sidepanel.frame.size = NSMakeSize(viewFrame.size.width, 200)
splitView.display()
}
These functions will probably methods in a class, they are for me. If your splitView can be nil you obviously have to check for that. This also assumes you have two subviews and the one at index 1, here as sidePanel is the one you want to collapse.
In Xcode 9.0 with Storyboards open Application Scene select View->Menu->Show sidebar. CTRL-click Show Sidebar, in sent actions delete the provided one, click on x. From the circle CTRL drag to First Responder in application scene and select toggleSideBar to connect to. Open storyboard and select the first split view item and in attributes inspector change behaviour from default to sidebar. Run and try with view menu item show/hide. All done in interface builder no code. toggleSideBar handles the first split view item. https://github.com/Dis3buted/SplitViewController
I got some artifacts with the code above, likely because it was out of context. I am sure it works where it was meant to. Anyway, here is a very streamlined implementation:
// this is the declaration of a left vertical subview of
// 'splitViewController', which is the name of the split view's outlet
var leftView: NSView {
return self.splitViewController.subviews[0] as NSView
}
// here is the action of a button that toggles the left vertical subview
// the left subview is always restored to 100 pixels here
#IBAction func someButton(sender: AnyObject) {
if splitViewController.isSubviewCollapsed(leftView) {
splitViewController.setPosition(100, ofDividerAtIndex: 0)
leftView.hidden = false
} else {
splitViewController.setPosition(0, ofDividerAtIndex: 0)
leftView.hidden = true
}
}
To see a good example using animations, control-click to download this file.
If your NSSplitView control is part of a NSSplitViewController object, then you can simply use this:
splitViewController.toggleSidebar(nil)