How to create dynamic stopping Scroll Rect in unity? - user-interface

I have an gameobject1(added Scroll Rect component)and inside of it another gameobject2(The Scroll rect component's content).In gameobject2 has images.The number of images can be 10 or 20..(Any numbers).The Movement Type is Elastic.As you know it will stop scrolling only until gameobject2 height's length. How to stop on dynamic number's of length.In gameobject2 the number of images can be different. It depends on search results. The results can be 5,8, or 200. So I need to scroll until last of search result.So how to stop scrolling on exactly length in Scroll rect component?

You can use ContentSizeFitter component. GameObject with name "Content", is a content for scrollRect component of "ScrollView"-gameObject.

RectTransform#SetSizeWithCurrentAnchors
I use this a lot when building dynamic scrolling lists. After adding all the items I want (and each having a known size, and all positioned using that size) I update the content's RectTransform with the new size (total number of objects added * size of the object).
For example, I have this code:
int i = 0;
//for each item in a list of skills...
IEnumerator<Skill> list = SkillList.getSkillList();
Transform skillListParent = GuiManager.instance.skillPanel.transform;
while(list.MoveNext()) {
Skill sk = list.Current;
//create a prefab clone...
GameObject go = Main.Instantiate(PrefabManager.instance.SKILL_LISTITEM, skillListParent) as GameObject;
//set its position...
go.transform.localPosition = new Vector3(5, i * -110 -5, 5);
//add a button event or other data (some lines omitted)...
Transform t1 = go.transform.FindChild("BuyOne");
t1.GetComponent<Button>().onClick.AddListener(delegate {
doBuySkill(sk);
});
t1.GetChild(0).GetComponent<Text>().text = Main.AsCurrency(sk.getCost(1)) + " pts";
//track how many...
i++;
}
//update rect transform
((RectTransform)skillListParent).SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, (i * 110 + 10));

Related

How to dynamically and automatically set FontSize based on view.Width?

"TRYING OUT AUTO SIZING"
Font size too large, so much so part of the string is cut off (when text is too large, a portion is cut off and replaced with ellipsis).
"test text"
Font size too small. The fontSize is a third of its respective view (estimating).
How to set the fontSize of an Element to the size of the Element (and or containing Views) width? Use the examples above as reference - "test text" would take up much more of the view and "TRYING OUT AUTO SIZING" would take up far less.
NOTE: Black boxes denote other elements.
The desired goal is an element (label and or containing view) that when text is changed at run-time, the fontSize is set according to the text assigned and width available to it (this remains constant after build). So that all text is viewable in the string and it uses the width available to it.
Purpose is to support multiple platforms on a variety of devices with widely different scaling.
Whats been tried? NamedSizes based on the idiom (phone/tablet/etc) and manipulating these with multiplication and division based on OS (platform, i.e., IOS, Android, etC). This can't be best practice and there must be a way to go about accomplish this.
Following Xamarin.Forms guide for "fitting text to available size" or "empirically fitting text" yields results that are not as expected.. "CH5: Dealing with sizes"
Please advise on best practice and/or next steps.
Struct
struct FontCalc
{
public FontCalc(Label label, double fontSize, double containerWidth)
: this()
{
// Save the font size.
FontSize = fontSize;
// Recalculate the Label height.
label.FontSize = fontSize;
SizeRequest sizeRequest =
label.Measure(containerWidth, Double.PositiveInfinity);
// Save that height.
TextHeight = sizeRequest.Request.Height;
}
public double FontSize { private set; get; }
public double TextHeight { private set; get; }
}
Implementation
Label label;
public EmpiricalFontSizePage()
{
label = new Label();
Padding = new Thickness(0, Device.RuntimePlatform == Device.iOS ? 30 : 0, 0, 0);
ContentView contentView = new ContentView
{
Content = label
};
contentView.SizeChanged += OnContentViewSizeChanged;
Content = contentView;
}
void OnContentViewSizeChanged(object sender, EventArgs args)
{
// Get View whose size is changing.
View view = (View)sender;
if (view.Width <= 0 || view.Height <= 0)
return;
label.Text =
"This is text displayed. Does it work?";
// Calculate the height of the rendered text.
FontCalc lowerFontCalc = new FontCalc(label, 10, view.Width);
FontCalc upperFontCalc = new FontCalc(label, 100, view.Width);
while (upperFontCalc.FontSize - lowerFontCalc.FontSize > 1)
{
// Get the average font size of the upper and lower bounds.
double fontSize = (lowerFontCalc.FontSize + upperFontCalc.FontSize) / 2;
// Check the new text height against the container height.
FontCalc newFontCalc = new FontCalc(label, fontSize, view.Width);
if (newFontCalc.TextHeight > view.Height)
{
upperFontCalc = newFontCalc;
}
else
{
lowerFontCalc = newFontCalc;
}
}
// Set the final font size and the text with the embedded value.
label.FontSize = lowerFontCalc.FontSize;
label.Text = label.Text.Replace("??", label.FontSize.ToString("F0"));
}
(implementation code from XF docs linked above)
One solution is to use the NuGet package: Forms9Patch
Using its Lines and AutoFit properties we can achieve our desired result. In our case, we want one line and we want our FontSize set to what is required to make our text fit within one line. Lines = 1, AutoFit = Forms9Patch.AutoFit.Width, and FontSize set to a large value (does not matter if it is well over our desired max as setting AutoFit to Width shrinks font till to what is required to make text fit within our specified number of lines) results in a Label that automatically adjusts its FontSize to the maximum space available to it given the text length.

How would i pass element's width and height to an effect or a custom renderer in XamarinForms

I'm not able to get the width nor the height of an element in the effects attaching to the element. I tried every single way:
void UpdateSize()
{
var _1 = ((BoxView)Element).Width; //-1
var _2 = ((BoxView)Element).WidthRequest; //-1
var _3 = ((BoxView)Element).Height; //-1
var _4 = ((BoxView)Element).HeightRequest; //-1
var _5 = Control.Width; //NaN (UWP). NaN is not a number
var _6 = Control.ActualWidth; //0
var _7 = Control.Height; //Nan (UWP). NaN is not a number
var _8 = Control.ActualHeight; //0
}
I even tried to pass the width and the height as a attached properties to the effect.
I need the width and height because i'm creating a drop shadow and I must resize the SpriteVisual to be the same size as the element.
May be the element draws after applying the renderer/effects so we have no size yet. If so, how to work around with this?
I would suggest to wire-up the SizeChanged event of Element when effect is attached and then creating your shadow once it fires. Also, make sure to unsubscribe the event when the effect is detached.

Pass gestures to children

I have an app with a game board and can pick up and move tiles around with panning using mr.gestures, that's working well.
My game board is a MR.Gestures.AbsoluteLayout and that's where I capture the panning gesture.
If I add that game board as a child to another MR.Gestures.AbsoluteLayout then it seems the gestures are blocked by the parent and it no longer works.
Is there a way to pass gestures though to children or ignore gestures on a parent in some way?
Is there a way to pass gestures though to children or ignore gestures
on a parent in some way?
For me this problem appeared only on Android.. The answer is Yes:
When parent receives gesture event it must check if finger x,y is within specific childs views. If yes, parent just ignores the gesture.
Regarding the code, ill just past one event handler to get the idea. In my case i have 2 childs (like and bookmark) over a parent frame:
//-------------------------------------------------------------------
private void OnTapped_MainFrame(object sender, TapEventArgs e)
//-------------------------------------------------------------------
{
//Get parent screen abs pos in pixels
//We are using native code get absolute screen position
var ptFrame = DependencyService.Get<INiftyHelpers>().GetViewAbsolutePosition((View)sender);
//Gets childs (hotspots) screen abs position in pixels
var ptFav = DependencyService.Get<INiftyHelpers>().GetViewAbsolutePosition((View)hsFav);
var ptLike = DependencyService.Get<INiftyHelpers>().GetViewAbsolutePosition((View)hsLike);
//Gets childs (hotspots) rectangles, everything in pixels using screen density
var rectFav = new Rectangle(ptFav, new Size(hsFav.Width * AppHelper.DisplayDensity, hsFav.Height * AppHelper.DisplayDensity));
var rectLike = new Rectangle(ptLike, new Size(hsLike.Width * AppHelper.DisplayDensity, hsLike.Height * AppHelper.DisplayDensity));
//Convert the finger XY to screen pos in pixels
var ptTouch = new Point(ptFrame.X + e.Center.X * AppHelper.DisplayDensity, ptFrame.Y + e.Center.Y * AppHelper.DisplayDensity); //absolute relative to screen
//check if withing childs
if (rectFav.Contains(ptTouch) || rectLike.Contains(ptTouch))
return; //Ignore input and let childs process their gestures!
//Process input
//..
}

How to make a menu with this effect in unity3d?

Sorry, I'll try to explain better.
I want to make a sliding menu where you can select a character. I want the character that is at the center increases in size to know that this is the current character. The effect can be seen in the game of Crossy Road when you want to select a character.
Sorry but I can't upload a imagen because i am new in the forum
I think I might be able to help you without needing too much borrowed code. There are two possibilities here:
You have a perspective camera so the "selected" item can just be closer to the camera.
You have an orthographic camera so you will have to scale things.
For perspective:
List<GameObject> characters; //contains all character.
int selectedIndex = 0; //index to the selected character.
float spacing = 10; //space between chars
void Update()
{
if(Input.GetKeyDown("RightArrow"))
{
selectIndex++;
ApplyChanges();
}
if(Input.GetKeyDown("LeftArrow"))
{
selectIndex--;
ApplyChanges();
}
}
void ApllyChanges()
{
// Make sure the selected index is within range and then space the characters.
selectedIndex = selectedIndex % character.Count();
SpaceCharacters();
}
void SpaceCharacters()
{
for(int i = 0; i < characters.Count(); ++i)
{
// characters on the left will have a negative spacing and so will be placed to the left and vice versa for characters on the right.
int offset = i - selectedIndex;
characters[i].transform.position = new Vector3(offset * spacing, 0, 0);
}
// Move the selected character closer.
characters[selectedIndex].transform.position = new Vector3(0,0,spacing);
}
For orthographic camera you will need to set the select characters transform.scale to a larger vector.
This won't animate anything or look cool. This code will just snap your characters into position.
The solution I adopted was to attach objects to the transparent buttons in a scrool rect, so as to manage 3d objects with the convenient of scrool rect interface.
Here you can find the official documentation for use scrool rect: http://docs.unity3d.com/Manual/script-ScrollRect.html
Maybe my assets can serve you ;)
https://www.assetstore.unity3d.com/en/#!/content/60233

iTextSharp: align image and text

I am using iTextSharp to export reports in PDF format. Reports' headers should have following format:
The problem is to align report header by center of the page, while there is an image on the left of the page. When I use a table, report header is aligned by center of its cell, not by center of the page. Is there a better approach?
EDIT:
Code for adding header is following:
var doc = new Document(pageSize, margins.Width, margins.Width, margins.Height, margins.Height);
using (PdfWriter.GetInstance(doc, destination))
{
doc.Open();
var headerTable = new PdfPTable(1){ WidthPercentage = 100 };
RenderHeader(headerTable); // adds several lines to headerTable
doc.Add(headerTable);
}
Do you really need a PdfPTable?
Why not add a Paragraph with the data that is right-aligned, followed by a couple of Paragraphs that are centered.
Then add the image at an absolute position, for instance:
Image img = Image.GetInstance(path_to_image);
img.SetAbsolutePosition(36, PdfWriter.getVerticalPosition(true));
document.Add(Image);
Another option is to add the Image in a table or a cell event instead of adding it straight to the table. Suppose that your PdfPTable consists of a single row and a single column, then you could define a cell event like this:
public class ImageCell : IPdfPCellEvent {
public void CellLayout(
PdfPCell cell, Rectangle position, PdfContentByte[] canvases
) {
float x1 = position.Left + 2;
float y1 = position.Top - 2;
float y2 = position.Bottom + 2;
PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
Image img = Image.GetInstance(path_to_image);
img.scaleToFit(10000, y1 - y2);
img.SetAbsolutePosition(x1, y2);
canvas.AddImage(img);
}
}
Suppose that cell is the PdfPCell with the date and the title, then you can do this:
cell.CellEvent = new ImageCell();
Note that in this case, the image will be scaled to the height of the cell.
Forgive me if the code doesn't compile right away, I'm writing this by heart (based on experience), I didn't test the actual code.

Resources