Xamarin.Forms: Scroll effect with collapsing sections of the screen - xamarin

I'm looking for help on how to do this effect:
On a page is a ListView that is 3cm from the top of the page, below a 3cm tall logo. When the user scrolls up the list view, the entire list view scrolls up to take up the 1/2 the space of the logo. Reverse when going down. So basically the Logo gets it's size allocation reduced. Both the logo and the listview can be in a scroll view, but how do I resize the logo

I'm posting the answer you placed on another site in case others searching for the solution only come across this article.
private const int ScrollMinLimit = 0;
private const int ScrollMaxLimit = 190;
private void ScrollView_Scrolled(object sender, ScrolledEventArgs e)
{
var val = MathHelper.ReMap(e.ScrollY, ScrollMinLimit, ScrollMaxLimit, 1, 0);
this.infoPanel.Scale = val;
this.infoPanel.Opacity = val;
}
and
public static class MathHelper
{
public static double ReMap(double oldValue, double oldMin, double oldMax, double newMin, double newMax)
{
return (((oldValue - oldMin) / (oldMax - oldMin)) * (newMax - newMin)) + newMin;
}
}

Related

Custom ListPopupWindow rendered in different widths

I am using Android.Support.V7.Widget.ListPopupWindow as a Drop-Down Menu from a Button within my layout. Here is the code snippet I am using
void MenuIcon_Click (object sender, EventArgs e)
{
popupWindow = new Android.Support.V7.Widget.ListPopupWindow (this);
popupAdapter = new MenuPopUpAdapter (this,selectedIndex,menuList);
popupAdapter.ItemClick+= PopupAdapter_ItemClick;
popupWindow.SetAdapter (popupAdapter);
popupWindow.AnchorView = menuButton;
Display display = WindowManager.DefaultDisplay;
Point size = new Point();
display.GetSize (size);
int width = size.X;
popupWindow.Width =160;
popupWindow.Show ();
}
But while debugging I noted that, even though I have given it a static width, it is rendered differently in different devices. What is causing this issue ?
This is because of the different screen densities in Android devices. You need to mention dimensions in DPs(Density Independent Pixels) to overcome this issue. This documentation from Google will be a nice read
You can get the corresponding pixel value to be mentioned while setting dimensions programatically from this method.
public int dpToPx(int dp) {
DisplayMetrics displayMetrics = Resources.DisplayMetrics;
int px = (int)Math.Round(dp * (displayMetrics.Density));
return px;
}
You may modify the code as above to fix the issue
popupWindow.Width =dpToPx(160);

Xamarin Forms fade to hidden?

In my current app, I have a bunch of buttons which can hide or show their corresponding stackLayout.
First, i tried using IsVisble property, but this causes a flash,
now im at using LayoutTo() which also flashes?
My code is as below:
async void btnStrike_Clicked(object sender, EventArgs args)
{
var layout = this.FindByName<StackLayout>("stkStrikeInfo");
var rect = new Rectangle(layout.X, layout.Y, layout.Width, layout.Height - layout.Height);
await layout.LayoutTo(rect, 2500, Easing.Linear);
}
Id like to animate the height!
Edit:
I found the following piece of code, which removes the Stacklayout from the page.
The issue now is that the view isnt updating?
I think you'll have better luck with just a default animation that reduces the height of the layout you want to hide to zero.
void btnStrike_Clicked(object sender, EventArgs args)
{
// get reference to the layout to animate
var layout = this.FindByName<StackLayout>("stkStrikeInfo");
// setup information for animation
Action<double> callback = input => { layout.HeightRequest = input; }; // update the height of the layout with this callback
double startingHeight = layout.Height; // the layout's height when we begin animation
double endingHeight = 0; // final desired height of the layout
uint rate = 16; // pace at which aniation proceeds
uint length = 1000; // one second animation
Easing easing = Easing.CubicOut; // There are a couple easing types, just tried this one for effect
// now start animation with all the setup information
layout.Animate("invis", callback, startingHeight, endingHeight, rate, length, easing);
}
If the layout is already hidden and you want to show it, you would replace
double startingHeight = layout.Height;
double endingHeight = 0;
with
double startingHeight = 0;
double endingHeight = 55;
The 55 is just an arbitrary height, if you want it to go back to the height from before, you would save the previous height to a variable before you hide it and use that saved height instead of 55.

Windows 7 Auto Size on mouse left?

I was wondering on windows 7 there is the function that when your mouse hits the form left/right top it will auto size the window to half the screen. I am trying to do that with my MDI Child. Here is the code that I have, however the function does not work.
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Form1 f1 = new Form1();
if (e.X == f1.Width/2 - 30)
{
Form activeChild = this.ActiveMdiChild;
activeChild.Width = this.Width / 2;
activeChild.Height = this.Height;
activeChild.Dock = DockStyle.Left;
}
}
You might try doing that on the Move event of the actual child form. Handling the event based on a new instance of Form1 in any event won't work very well. Anyhow, here's some code as it would look inside the child. (Ugly, but it at least does something.)
private void SubForm_Move(object sender, EventArgs e)
{
if (Location.X <= 0)
{
Width = MdiParent.Width / 2;
Height = MdiParent.Height;
Location = new Point(0,0);
Dock = DockStyle.Left;
}
}

BlackBerry - Custom centered cyclic HorizontalFieldManager

Trying to create a custom cyclical horizontal manager which will work as follows. It will control several field buttons where the buttons will always be positioned so that the focused button will be in the middle of the screen. As it is a cyclical manager once the focus moves to the right or left button, it will move to the center of the screen and all the buttons will move accordingly (and the last button will become the first to give it an cyclic and endless list feeling)
Any idea how to address this?
I tried doing this by implementing a custom manager which aligns the buttons according to the required layout. Each time moveFocus() is called I remove all fields (deleteAll() ) and add them again in the right order.
Unfortunately this does not work.
Using HorizontalButtonFieldSet class from KB How to - Implement advanced buttons, fields, and managers:
class CentricHManager extends HorizontalButtonFieldSet {
int focusedFieldIndex = 0;
public void focusChangeNotify(int arg0) {
super.focusChangeNotify(arg0);
int focusedFieldIndexNew = getFieldWithFocusIndex();
if (focusedFieldIndexNew != focusedFieldIndex) {
if (focusedFieldIndexNew - focusedFieldIndex > 0)
switchField(0, getFieldCount() - 1);
else
switchField(getFieldCount() - 1, 0);
}
}
private void switchField(int prevIndex, int newIndex) {
Field field = getField(prevIndex);
delete(field);
insert(field, newIndex);
}
public void add(Field field) {
super.add(field);
focusedFieldIndex = getFieldCount() / 2;
setFieldWithFocus(getField(focusedFieldIndex));
}
}

Java - drawing many images with Graphics.drawImage() and 2-screen buffer strategy distorts and cuts images

I am using a loop to invoke double buffering painting. This, together with overriding my only Panel's repaint method, is designed to pass complete control of repaint to my loop and only render when it necessary (i.e. some change was made in the GUI).
This is my rendering routine:
Log.write("renderer painting");
setNeedsRendering(false);
Graphics g = frame.getBufferStrategy().getDrawGraphics();
g.setFont(font);
g.setColor(Color.BLACK);
g.fillRect(0, 0, window.getWidth(),window.getHeight());
if(frame != null)
window.paint(g);
g.dispose();
frame.getBufferStrategy().show();
As you can see, it is pretty standard. I get the grpahics object from the buffer strategy (initialized to 2), make it all black and pass it to the paint method of my "window" object.
After window is done using the graphics object, I dispose of it and invoke show on the buffer strategy to display the contents of the virtual buffer.
It is important to note that window passes the graphics object to many other children components the populate the window and each one, in turn, uses the same instance of the graphics object to draw something onto the screen: text, shapes, or images.
My problem begins to show when the system is running and a large image is rendered. The image appears to be cut into seveeal pieces and drawn again and again (3-4 times) with different offsets inside of where the image is supposed to be rendered. See my attached images:
This is the original image:
alt text http://img109.imageshack.us/img109/8308/controller.png
This is what I get:
alt text http://img258.imageshack.us/img258/3248/probv.png
Note that in the second picture, I am rendering shapes over the picture - these are always at the correct position.
Any idea why this is happening?
If I save the image to file, as it is in memory, right before the call to g.drawImage(...) it is identical to the original.
Uh, you are using Swing ?
Normally Swing automatically renders the image, you can't switch it off. The repaint()
method is out of bounds because Swing has a very complicated rendering routine due to
method compatibility for AWT widgets and several optimizations, inclusive drawing only
when necessary !
If you want to use the High-Speed Drawing API, you use a component with a BufferStrategy
like JFrame and Window, use
setIgnoreRepaint(false);
to switch off Swing rendering, set up a drawing loop and paint the content itself.
Or you can use JOGL for OpenGL rendering. The method you are using seems completely
at odds with correct Java2D usage.
Here the correct use:
public final class FastDraw extends JFrame {
private static final transient double NANO = 1.0e-9;
private BufferStrategy bs;
private BufferedImage frontImg;
private BufferedImage backImg;
private int PIC_WIDTH,
PIC_HEIGHT;
private Timer timer;
public FastDraw() {
timer = new Timer(true);
JMenu menu = new JMenu("Dummy");
menu.add(new JMenuItem("Display me !"));
menu.add(new JMenuItem("Display me, too !"));
JMenuBar menuBar = new JMenuBar();
menuBar.add(menu);
setJMenuBar(menuBar);
setIgnoreRepaint(true);
setVisible(true);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
super.windowClosing(evt);
timer.cancel();
dispose();
System.exit(0);
}
});
try {
backImg = javax.imageio.ImageIO.read(new File("MyView"));
frontImg = javax.imageio.ImageIO.read(new File("MyView"));
}
catch (IOException e) {
System.out.println(e.getMessage());
}
PIC_WIDTH = backImg.getWidth();
PIC_HEIGHT = backImg.getHeight();
setSize(PIC_WIDTH, PIC_HEIGHT);
createBufferStrategy(1); // Double buffering
bs = getBufferStrategy();
timer.schedule(new Drawer(),0,20);
}
public static void main(String[] args) {
new FastDraw();
}
private class Drawer extends TimerTask {
private VolatileImage img;
private int count = 0;
private double time = 0;
public void run() {
long begin = System.nanoTime();
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
GraphicsConfiguration gc = g.getDeviceConfiguration();
if (img == null)
img = gc.createCompatibleVolatileImage(PIC_WIDTH, PIC_HEIGHT);
Graphics2D g2 = img.createGraphics();
// Zeichenschleife
do {
int valStatus = img.validate(gc);
if (valStatus == VolatileImage.IMAGE_OK)
g2.drawImage(backImg,0,0,null);
else {
g.drawImage(frontImg, 0, 0, null);
}
// volatile image is ready
g.drawImage(img,0,50,null);
bs.show();
} while (img.contentsLost());
time = NANO*(System.nanoTime()-begin);
count++;
if (count % 100 == 0)
System.out.println(1.0/time);
}
}

Resources