How can I build three buttons touching horizontally in Unity GUI - c#

I'm trying to build a custom EditorWindow in Unity and I want to have the effect like in the picture with the buttons acting like tabs.
I tried to place the buttons horizontally and have negative spaces between them but is not quite the effect I want. Below is my code.
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Heightmap")) { }
GUILayout.Space(-10);
if (GUILayout.Button("Vegetation")) { }
GUILayout.Space(-10);
if (GUILayout.Button("Details")){ }
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();

Use GUILayout.Toolbar:
using UnityEngine;
using UnityEditor;
public class MyWindow : EditorWindow
{
int toolbarInt = 0;
string[] toolbarStrings = {"Heightmap", "Vegetation", "Details"};
// Add menu named "My Window" to the Window menu
[MenuItem("Window/My Window")]
static void Init()
{
// Get existing open window or if none, make a new one:
MyWindow window = (MyWindow)EditorWindow.GetWindow(typeof(MyWindow));
window.Show();
}
void OnGUI()
{
toolbarInt = GUILayout.Toolbar(toolbarInt, toolbarStrings);
switch (toolbarInt)
{
case 0:
GUILayout.Button("Content for Heightmap");
break;
case 1:
GUILayout.Button("Content for Vegetation");
break;
case 2:
GUILayout.Button("Button for Details");
break;
}
}
}

Related

Change Button Colors with a click

im starting to code with c# and i have a problem. Basically, i want to jump colors clockwise. For example, if i click the orange button the gold button turns white and the second button turns gold. I want to do that for all buttons until the button bellow gold button be gold and the others stay white (clockwise)
You can see what i explained above in this image.
The only code that i have for now is:
if (button9.Enabled)
{
button2.BackColor = Color.Gold;
button1.BackColor = Color.White;
}
Button 9 is the jump button.
If you could help me i would be very grateful.
Here is an simple WinForm example
You can follow the serial number (1.1 ~ 4.2) in the code comment to get the code idea :)
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace WinFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// 2.1 initialize a list, and add all buttons into it.
this.Buttons.Add(button2);
this.Buttons.Add(button3);
this.Buttons.Add(button4);
// 2.2. initialize high light index.
HighlightIndex = 0;
// 2.3. refresh all buttons' color.
RefreshColor();
}
// 1.1 we use this List to store all buttons.
private List<Button> Buttons = new List<Button>();
// 1.2 indicated the index of the highlighted button
private int HighlightIndex = 0;
private void button1_Click(object sender, System.EventArgs e)
{
// 4.1 when user click the jump button, increme the highlight index.
HighlightIndex = HighlightIndex + 1;
if (HighlightIndex >= Buttons.Count)
{
HighlightIndex = 0;
}
// 4.2 refresh all buttons' color.
RefreshColor();
}
private void RefreshColor()
{
// 3.1 loop all buttons by index.
for (int i = 0; i < Buttons.Count; i++)
{
if (i == HighlightIndex)
{
// 3.2 if the index equals the highlight button index, update BackColor as Gold.
Buttons[i].BackColor = Color.Gold;
}
else
{
// 3.3 set normal button BackColor as White.
Buttons[i].BackColor = Color.White;
}
}
}
}
}

How can I add word wrap to EditorGUILayout.TextArea?

How can I add word wrap to the editor textarea? I'm trying to mimic the [TextArea] attribute (word wrap, automatically increase height when needed)
I know that GUILayout.TextArea() works but I was hoping to use EditorGUILayout because according to the docs it correctly responds to copy/pasting, select all, etc.
My code:
obj.talkableFlavorText = EditorGUILayout.TextArea(obj.talkableFlavorText, GUILayout.MinHeight(textAreaHeight));
Use a GUIStyle and set the wordWrap property to true.
Complete example based on Unity Editor Window Example
using UnityEngine;
using UnityEditor;
public class MyWindow : EditorWindow
{
string myString = "Hello World";
// Add menu named "My Window" to the Window menu
[MenuItem("Window/My Window")]
static void Init()
{
// Get existing open window or if none, make a new one:
MyWindow window = (MyWindow)EditorWindow.GetWindow(typeof(MyWindow));
window.Show();
}
void OnGUI()
{
GUIStyle style = new GUIStyle(EditorStyles.textArea);
style.wordWrap = true;
myString = EditorGUILayout.TextArea(myString, style);
}
}
Result:

Xamarin Forms Nested Tabs

I've noticed it's possible to create a mobile app with nested tabs.
Is this possible in Xamarin Forms?
Please see screen shot below:
I can create the bottom tabs on iOS using TabbedPage, but how do I create the nested tabs at the top of the page?
Thank you
The same way you would do on the native app. There are no native nested tabs, so Xamarin can't support it as such thing doesn't exist.
In the native app you have the control at the top (called SegmentedControl on iOS and on Android there is no such control out of the box) where you pick the value and then change the view below manually when it is clicked.
Is this possible in Xamarin Forms?
Yes,of course.You can use CustomRenderer to implement it.Refer to the following code.
in iOS Project . Create a pageRenderer
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using app1;
using app1.iOS;
using UIKit;
using Foundation;
using CoreGraphics;
using ObjCRuntime;
[assembly:ExportRenderer(typeof(MyPage1),typeof(MyPageRenderer))]
namespace app1.iOS
{
public class MyPageRenderer:PageRenderer
{
public MyPageRenderer()
{
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (ViewController != null)
{
NSArray items = NSArray.FromStrings(new string[] { "Courses", "Favourite", "Recent" });
UISegmentedControl segmentedControl = new UISegmentedControl(items)
{
Frame = new CGRect(50, 20, NativeView.Bounds.Width - 100, 35)
};
segmentedControl.SelectedSegment = 0;
segmentedControl.TintColor = UIColor.Red;
segmentedControl.ApportionsSegmentWidthsByContent = true; //Change the width of the segment based on the content of the segment
segmentedControl.AddTarget(this, new Selector("ValueChanged:"), UIControlEvent.ValueChanged);
NativeView.AddSubview(segmentedControl);
}
}
[Export("ValueChanged:")]
void ValueChanged(UISegmentedControl sender)
{
MessagingCenter.Send<Object, int>(this, "ClickSegmentedControl", (int)sender.SelectedSegment);
// switch((int)sender.SelectedSegment){
// case 0:
// break;
// case 1:
// break;
// case 2:
// break;
// default:
// break;
//}
}
}
}
in Forms ,you can subscribe the message .if you want to handle the event in forms when you click the segmented .
public MyPage1()
{
//...
MessagingCenter.Subscribe<Object, int>(this, "ClickSegmentedControl", (sender, arg) =>
{
Console.WriteLine(arg); //arg is num of the segment that you clicked.
});
}

XAMARIN: How to Refresh WebView OnTabReselected?

I'm trying to refresh a WebView when the user reselects a tab that is already selected on Android coding with Xamarin using deprecated Actionbar and TabHost.
I've got this code
public void OnTabReselected(WhatsOnActivity tab, FragmentTransaction ft)
{
WebView whatsOnWebView = FindViewById<WebView>(Resource.Id.webViewWhatsOn);
//tell webview to reload
whatsOnWebView.Reload();
}
and I've tried to put that code into both my MainActivity and inside My WhatsOnActivity
It doesn't crash the app, but it also doesn't reload the tab. In Xamarin, can I use the "WhatsOnActivity" as the tab in my method? I have a feeling that's what I'm doing wrong.. but if I try to use tab ids, they're not recognized by the IDE. Can anyone give me direction on what I've done wrong?
my complete code can be found here:
https://github.com/hexag0d/BitChute_Mobile_Android_a2/blob/2.68/MainActivity.cs
if you're wondering about the context.
Update
Try to set OnClicklistener on your first tab. Set the listener after you add tabs.
TabHost.TabWidget.GetChildAt(0).SetOnClickListener(new MyOnClickListener(tabHost));
And the listener:
public class MyOnClickListener : Java.Lang.Object, IOnClickListener
{
TabHost tabHost;
public MyOnClickListener(TabHost tabHost)
{
this.tabHost = tabHost;
}
public void OnClick(View v)
{
var parentView = ((ViewGroup)((ViewGroup)tabHost.GetChildAt(0)).GetChildAt(1)).GetChildAt(0);
WebView whatsOnWebView = parentView.FindViewById<WebView>(Resource.Id.webViewWhatsOn);
whatsOnWebView.Reload();
tabHost.CurrentTab = 0;
}
}
And the result is:
Original answer
Please try to add an OnTabChangeListener to your TabHost.
For example, In your MainActivity OnCreate():
TabHost tabHost = FindViewById<TabHost>(Android.Resource.Id.TabHost);
tabHost.SetOnTabChangedListener(new MyOnTabChangedListener(tabHost));
And the MyOnTabChangedListener:
public class MyOnTabChangedListener : Java.Lang.Object, IOnTabChangeListener
{
TabHost tabHost;
public MyOnTabChangedListener(TabHost tabHost)
{
this.tabHost = tabHost;
}
public void OnTabChanged(string tabId)
{
if(tabId == "whats_on")
{
var parentView = ((ViewGroup)((ViewGroup)tabHost.GetChildAt(0)).GetChildAt(1)).GetChildAt(0);
WebView whatsOnWebView = parentView.FindViewById<WebView>(Resource.Id.webViewWhatsOn);
whatsOnWebView.Reload();
}
}
}
First off thank you so much to #Billy Liu - MSFT !!! dude is a lifesaver. He knows his Xamarin. Alright, so here's how you can refresh a tab OnClick
//Assemblies
using System;
using System.Threading.Tasks;
using Android.App;
using Android.Content;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Widget;
using Android.Webkit;
using static Android.Widget.TabHost;
using static Android.Views.View;
using Android.Views;
//this assembly is your Activities class, which should contain your class instances
using com.xamarin.example.BitChute.Activities;
EDIT: Put these click listeners inside your MainActivity.cs .. the int inside GetChildAt() represents the tab our listener will respond to. int 0 = tab farthest left and they go up 0 .. 1 .. 2 .. etc .. 1 would mean tab second from the left. Each listener will need it's own listener class instance. I'll show two examples in the next block.
TabHost tabHost = FindViewById<TabHost>(Android.Resource.Id.TabHost);
tabHost.Setup();
tabHost.TabWidget.GetChildAt(0).SetOnClickListener(new WhatsOnClickListener(tabHost));
tabHost.TabWidget.GetChildAt(1).SetOnClickListener(new SubsClickListener(tabHost));
tabHost.TabWidget.GetChildAt(2).SetOnClickListener(new DiscoverClickListener(tabHost));
tabHost.TabWidget.GetChildAt(3).SetOnClickListener(new MyChannelClickListener(tabHost));
tabHost.TabWidget.GetChildAt(4).SetOnClickListener(new SettingsClickListener(tabHost));
EDIT: Create a separate ClickActivity.cs file and then add these listeners into it. you will need to create an OnClickListener instance for each tab. This example is only two of the listeners; but if you're using my template, you will need to use these examples to create another 3 listeners.
public class WhatsOnClickListener : Java.Lang.Object, IOnClickListener
{
TabHost tabHost;
//this int will tell the click listener whether to reload the webview or pop 2 root
static int tbC = 0;
public WhatsOnClickListener(TabHost tabHost)
{
//tell the clicklistener which tabhost to use
this.tabHost = tabHost;
}
//this class handles the click event
public void OnClick(View v)
{
//declare the webview and tell our object where to find the XAML resource
WebView webViewWhatsOn = tabHost.CurrentView.FindViewById<WebView>(Resource.Id.webViewWhatsOn);
//...if the CurrentTab != 0 ... we won't fire the Reload() or LoadUrl()
//..without this logic, the app will crash because our WebViews
//.aren't set to an instance of an object
if (tabHost.CurrentTab == 0)
{
//if tbC int is 0, we will reload the page
if (tbC == 0)
{
//tell whatsOnWebView to Reload
webViewWhatsOn.Reload();
//set the int to one so next time webview will pop to root
tbC = 1;
}
//else if the int is 1, we will pop to root on tab 0
else if (tbC == 1)
{
//tell whatsOnWebView to pop to root
webViewWhatsOn.LoadUrl(#"https://bitchute.com/");
//set the tbC int so that next time webview will reload
tbC = 0;
}
}
//if our current tab isn't zero, we need to set CurrentTab to 0
//this line is critical or our tabs won't work when not selected
tabHost.CurrentTab = 0;
}
}
public class SubsClickListener : Java.Lang.Object, IOnClickListener
{
TabHost tabHost1;
static int tbC = 0;
public SubsClickListener(TabHost tabHost1)
{
this.tabHost1 = tabHost1;
}
public void OnClick(View v)
{
if (tabHost1.CurrentTab == 1)
{
WebView subWebView = tabHost1.CurrentView.FindViewById<WebView>(Resource.Id.webViewSubs);
if (tbC == 0)
{
subWebView.Reload();
tbC = 1;
}
else if (tbC == 1)
{
subWebView.LoadUrl(#"https://bitchute.com/subscriptions/");
tbC = 0;
}
}
tabHost1.CurrentTab = 1;
}
}
hope that helps! I've been trying this for a minute.

Enable a button to be clicked at design-time in Visual Studio?

My setting:
I've got a C# application (.NET 3.5) in Visual Studio 2008. No chance to switch to WPF or whatsoever :).
My app contains a custom control (a button class derived from Windows.Forms.Button) that acts as a replacement for the Windows.Forms.TabControl. I can associate these buttons with one another and each button can be associated with one control that it is dealing with (usually some sort of Windows.Forms.Panel). It looks something like this:
public class TabButton : System.Windows.Forms.Button
{
// ...
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
this.myAssociatedControl.Visible = true;
this.tellMyBuddiesToHideTheirControls();
}
// ...
}
Basically it is just about clicking a button, showing its bound control and having the controls bound to the associated buttons disappear - just like the TabControl, but the approach is easily designable and I can place the buttons far from their content panels.
The problem:
This works pretty well at runtime, but the usage at design time is arguably odd: With the mouse, find a control that´s belonging to the group and run a series of <Send To Back>s until the desired control is visible.
The question:
Is there a way to tell the VS designer to evaluate the clicks on the buttons at design time like it does with the TabControl so that I can switch the tabs just by clicking them like I would at runtime?
I've been searching for quite a while now. There are some articles here at SO but they only seem to cover adding additional attributes to the properties designer.
Edith says:
By request, an answer to my own question ...
This is the solution that is suitable to my application. It is basically an example from the msdn with some twists to get the custom designer to use a callback on click. Hope it helps anyone :-).
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class TabButtonDesigner : System.Windows.Forms.Design.ControlDesigner
{
ShowTabGlyph myGlyph = null;
Adorner myAdorner;
public TabButtonDesigner()
{
}
public override void Initialize(IComponent component)
{
base.Initialize(component);
// Add the custom set of glyphs using the BehaviorService.
// Glyphs live on adornders.
myAdorner = new Adorner();
BehaviorService.Adorners.Add(myAdorner);
myGlyph = new ShowTabGlyph(BehaviorService, Control);
myGlyph.Callback = () =>
{
((MyCustomTabButton)this.Control).ShowMyTab();
};
myAdorner.Glyphs.Add(myGlyph);
}
class ShowTabGlyph : Glyph
{
Control control;
BehaviorService behaviorSvc;
public Action Callback
{
get;
set;
}
public ShowTabGlyph(BehaviorService behaviorSvc, Control control) :
base(new ShowTabBehavior())
{
this.behaviorSvc = behaviorSvc;
this.control = control;
}
public override Rectangle Bounds
{
get
{
// Create a glyph that is 10x10 and sitting
// in the middle of the control. Glyph coordinates
// are in adorner window coordinates, so we must map
// using the behavior service.
Point edge = behaviorSvc.ControlToAdornerWindow(control);
Size size = control.Size;
Point center = new Point(edge.X + (size.Width / 2),
edge.Y + (size.Height / 2));
Rectangle bounds = new Rectangle(
center.X - 5,
center.Y - 5,
10,
10);
return bounds;
}
}
public override Cursor GetHitTest(Point p)
{
// GetHitTest is called to see if the point is
// within this glyph. This gives us a chance to decide
// what cursor to show. Returning null from here means
// the mouse pointer is not currently inside of the glyph.
// Returning a valid cursor here indicates the pointer is
// inside the glyph, and also enables our Behavior property
// as the active behavior.
if (Bounds.Contains(p))
{
return Cursors.Hand;
}
return null;
}
public override void Paint(PaintEventArgs pe)
{
// Draw our glyph. It is simply a blue ellipse.
pe.Graphics.DrawEllipse(Pens.Blue, Bounds);
}
// By providing our own behavior we can do something interesting
// when the user clicks or manipulates our glyph.
class ShowTabBehavior : Behavior
{
public override bool OnMouseUp(Glyph g, MouseButtons button)
{
//MessageBox.Show("Hey, you clicked the mouse here");
//this.
ShowTabGlyph myG = (ShowTabGlyph)g;
if (myG.Callback != null)
{
myG.Callback();
}
return true; // indicating we processed this event.
}
}
}
}
[DesignerAttribute(typeof(TabButtonDesigner))]
public class MyCustomTabButton : System.Windows.Forms.Button
{
// The attribute will assign the custom designer to the TabButton
// and after a rebuild the button contains a centered blue circle
// that acts at design time like the button in runtime does ...
// ...
}

Categories