I want to add a background to the prefab when it clicked as it should look as its selected I have added the click listener which is working but I'm not able to add a background
for (int i = 0; i < list.Count; i++) {
GameObject tempobj = Instantiate (amtPrefab);
listGameObject.Add(tempobj);
tempobj.GetComponent<Button>().onClick.AddListener(() =>
OnButtonClick(tempobj)
);
}
I'm using this code and I want to change the color in the OnButtonClick method that i'm passing the clicked object to
Thanks in advance for the help
Use Ui Button how you are doing currently and in your Background image of your prefab add your script to change the color.
Subscribe to the click event:
tempobj.GetComponent<Button> ().onClick.AddListener(() => OnButtonClick(tempobj));
And only need to call your delegate event OnButtonClick()
void OnButtonClick()
{
//change backgroung color code here
}
Related
I'm currently making a quiz game that has three buttons, from an object pool, and I want them to turn green or red depending on whether or not they are the correct answer. This works perfectly.
When I add the coRoutine to change the button back to clear so the next question can be answered, the button almost never changes color after clicking and essentially nothing happens. Would really appreciate any help!! Thank you.
public void HandelClick()
{
var colors = GetComponent<Button> ().colors;
if( ! answerData.isCorrect)
{
colors.normalColor = Color.red;
GetComponent<Button>().colors = colors;
}
else
{
colors.normalColor = Color.green;
GetComponent<Button> ().colors = colors;
playerMovement.dodge();
}
StartCoroutine("Revert");
//gameController.AnswerButtonClicked(answerData.isCorrect);
}
IEnumerator Revert()
{
Debug.Log(" we are reverting " + Time.time);
yield return new WaitForSeconds(1.8f);
Debug.Log(" we are reverting again " + Time.time);
var colors = GetComponent<Button> ().colors;
colors.normalColor = Color.clear;
GetComponent<Button> ().colors = colors;
gameController.AnswerButtonClicked(answerData.isCorrect);
}
Changing the colors works as you said (you can see that in the Inspector of the Button)
The problem is that the Image component's color doesn't get updated automatically since the Button isn't receiving any pointer event like PointerDown, PointerExit etc => the new color is not applied to the Image (only in the cases where you do a new pointer event like enter, exit, up or down).
You could solve this by doing
GetComponent<Image>().color = colors.normalColor;
additional everywhere you change it.
Note: In general you should use GetComponent only once in Awake
private Button _button;
private Image _image;
private void Awake()
{
_button = GetComponent<Button>();
_image = GetComponent<Image>();
}
and than reuse the references _image and _button
I'm trying to create a scroll grid view in which every cell object is tapable.
When a cell object is tapped I want to scale and traslate it to the center of the screen and render it above other cells.
I was able to make it tapable and scale it in its position. Now I want to move the cell object to the center of the screen and render it above other cells.
I've tried many solutions but none of them works.
This is my hierarchy:
This is the grid in normal state:
This is the grid when a cell was tapped:
I'm populating the grid from a C# script dynamically.
void Populate()
{
GameObject cardContainerInstance, cardInstance;
foreach (var c in cardsCollection.GetAll())
{
if (c.IsOwned)
{
cardContainerInstance = Instantiate(cardContainer, transform);
cardInstance = cardContainerInstance.transform.Find("Card").gameObject;
var cardManager = cardInstance.GetComponent<CardManager>();
cardManager.card = c;
cardManager.AddListener(this);
}
else
{
Instantiate(cardSlot, transform);
}
}
}
public void OnCardClick(GameObject cardObject, Card card)
{
Debug.Log("OnCardClick " + card.name);
if (openedCard != null) {
if (openedCard.Number == card.Number)
{
CloseCard(openedCardObject);
}
else
{
CloseCard(openedCardObject);
OpenCard(cardObject, card);
}
}
else
{
OpenCard(cardObject, card);
}
}
void OpenCard(GameObject cardObject, Card card)
{
//cardObject.GetComponent<Canvas>().sortingOrder = 1;
var animator = cardObject.GetComponent<Animator>();
animator.SetTrigger("Open");
openedCard = card;
openedCardObject = cardObject;
}
void CloseCard(GameObject cardObject)
{
var animator = cardObject.GetComponent<Animator>();
animator.SetTrigger("Close");
openedCard = null;
openedCardObject = null;
}
I can't figure out how to move the cell to the center and render it above others.
Note that all is animated using an animator attached to the object itself.
Could anyone help me please? Thank you very much!
EDIT: more details
All cell object have the following hierarchy:
where:
CardContainer is an empty object added to use animator on Card child object
Card is the object itself that has a script, a canvas renderer and an animator
StatsImage is the object that slide out when the card is tapped
Image is a calssic UIImage with Image script, Shadow script and canvas renderer
Other component are simple texts.
EDIT: fix in progress
Trying to apply this suggestions I was able to manage the rendering order (as you see on the image below) but it seems that prevent touch events to be detected on the game object.
I've added a GraphicsRaycaster too and now the bottom horizontal scroll view scrolls again but only if I click and drag a card.
Moreover, with the GraphicsRaycaster, the main grid card still are not clickable and it's possible to open the card only if it is behind the bottom panel (if I click on the red spot in the image below the card behind the panel receives che click)
This is the CardContainer at runtime(note that I'm attaching new Canvas and GraphicsRaycaster on the CardContainer, which is the "root" element):
You didn't clarify whether you are using a sprite renderer or some other method but here is an answer for each.
Sprite renderer:
this the simple one. In each sprite renderer, there is a variable called "sortingOrder" in script and "Order in layer" in the inspector. sprite renderer with sorting Orders that are higher is rendered first. All you would need to do is call:
cardObject.GetComponent<SpriteRenderer>().sortingOrder = 1;
when you click the card, and
cardObject.GetComponent<SpriteRenderer>().sortingOrder = 0;
when you unclick it. I hope that makes sense!
Other Method:
this one is a bit harder and I would suggest that you switch to sprite renderers and it will be much easier and more stable down the road, but I can understand if you have already written a lot of scripts and don't want to go back and change them.
Anyway, all you will need to do Is create two layers: cardLower and cardUpper. then create a new camera and call it topCamera. now under the top camera object in the inspector, change the culling mask (it's near the top) and make sure cardUpper is selected. then change the Clear flags (first one) to "Don't Clear" finally change the depth to 0 (if that doesn't work change it to -2). Now objects in the cardUpper will always be rendered above everything else. You can change the layer through script with
cardObject.layer = "cardUpper"
or
cardObject.layer = "cardLower"
I hope that helps!
Ok, so its pretty simple. So you are going to want to add another canvas component to the game object, and check the override sorting to true. Then use
cardObject.GetComponent<Canvas>().sortingOrder = 1;
to place it in the front and
cardObject.GetComponent<Canvas>().sortingOrder = 0;
to put it in the back.
you are also going to need to put a GraphicsRaycaster on to each of the cardObjects
Ignore my other answer about sprite renderers, they are not needed here
My game uses a registration form scene in order to register a user. I've got several Textboxes(UIInput) on screen.
I would like to have Next/Previous Button over the keyboard which appears when i select a text box for input. this way i will be able to navigate on multiple textboxes in the registration form.
right now i am using HideInput=true so there is nothing over the keyboard
I am sure you have Box Collider "using UIInput",
Simple way would be to add UIButton To your InputBox.
Once you do that attach scene GameObject or PrefabObject, with a public method() to the UIButton OnClick Notify option, Select Method from the drop down.
Test Code:
Private Bool ShwNxtBtn = false;
Public Void MethodName(){
if (ShwNxtBtn != true){
ShwNxtBtn = true;
}else{
ShwNxtBtn = false;
}
Note: you could use Toggle, but I've had some issue with that and input Collider.
I am looking to add a button to a menu screen, it does not need to be anything complicated, in fact, the easier the better!
The project is a Cocos2d-x project, and here is the existing start button code;
fileName = (CCString*)sc->imageDict->objectForKey("GUI_StartButton-image");
CCSprite *startGameSprite = CCSprite::createWithSpriteFrameName( fileName->m_sString.c_str() );
CCSprite *startGameSpriteClick = CCSprite::createWithSpriteFrameName( fileName->m_sString.c_str() );
startGameSpriteClick->setColor( ccc3(128, 128, 128) );
CCMenuItemSprite *startGameItem = CCMenuItemSprite::create(startGameSprite, startGameSpriteClick, NULL, this, menu_selector(MainMenu::menuStartGameCallback));
startGameItem->setPosition( GameController::sharedGameController()->getPositionOfUIItem( "GUI_StartButton-image" ) );
pMenu = CCMenu::create(startGameItem, NULL);
All I want to do is add another button and call it 'Information'
I can create the image.png for it no problem, but if anyone could assist in helping me with what I need to type for the button to appear, for the moment, let's use hard coded values, say for example, to put it in the top left hand corner of the screen if possible?
I guess it needs an action to tell it what to do when pressed, I have code that I can put inside that, but I am not sure what I need to put to call the action, ordinarily it would be a void or IBAction but this is Cocos so I am unfamiliar with it.
Would appreciate any assistance! Thanks :)
Chris
Have you added the menu as a child to your scale/current layer?
Until you add it as as a child node it will not be rendered.
I would create a menu as follows:
// create the sprites for button up and button down
CCSprite* startGameSprite = CCSprite::createWithSpriteFrameName("start_button_up.png");
CCSprite* startGameSpriteClick = CCSprite::createWithSpriteFrameName("start_button_down.png");
// create a menu item (button) with the up/down sprites
CCMenuItemSprite* startGameItem = CCMenuItemSprite::create(startGameSprite, startGameSpriteClick, this, menu_selector(MainMenu::menuStartGameCallback));
// create a menu to hold the buttons (remembering to NULL terminate the list)
CCMenu *menu = CCMenu::create(startGameItem, NULL);
// position the entire menu
menu->setPosition(0,0);
// add it as a child (so it appears
this->addChild(menu);
Notes:
menu_selector(MainMenu::menuStartGameCallback)
This tells the CCMenuItemSprite which function to call when a touch is detected, and should be a function in the class MainMenu of the following structure:
void MainMenu::menuStartGameCallback(CCObject* sender)
{
CCLOG("Hello!");
}
Remember to declare this function in MainMenu.h
Now, to add another button to this menu you just need to make an addition to the above code:
// NEW /////////
CCSprite* informationSprite = CCSprite::createWithSpriteFrameName("info_button_up.png");
CCSprite* informationSpriteClick = CCSprite::createWithSpriteFrameName("info_button_down.png");
CCMenuItemSprite* infoGameItem = CCMenuItemSprite::create(informationSprite, informationSpriteClick, this, menu_selector(MainMenu::menuInfoCallback));
// END NEW //////
CCSprite* startGameSprite = CCSprite::createWithSpriteFrameName("start_button_up.png");
CCSprite* startGameSpriteClick = CCSprite::createWithSpriteFrameName("start_button_down.png");
// create a menu item (button) with the up/down sprites
CCMenuItemSprite* startGameItem = CCMenuItemSprite::create(startGameSprite, startGameSpriteClick, this, menu_selector(MainMenu::menuStartGameCallback));
// create a menu to hold the buttons (remembering to NULL terminate the list)
// NEW - we include the new info item
CCMenu *menu = CCMenu::create(startGameItem, infoGameItem, NULL);
// position the entire menu
menu->setPosition(0,0);
// add it as a child (so it appears
this->addChild(menu);
Remembering to create the callback function:
void MainMenu::menuInfoCallback(CCObject* sender)
{
CCLOG("Information!");
}
My app has a sliding drawer for notifications. I've managed to get it to function like the android notifications including the "clear all" button.
When the clear all button is clicked my database is cleared, my list adapter is refreshed, and my list adapter gets set to the list. The view updates and the list is cleared.
When I added slide-out animation (just like jelly bean) I got a NullPointerException. The issue crops up when my adapter is set. If I comment out setting the adapter the animation runs without a problem.
// Animation
int count = drawer_list.getCount();
for (int i = 0; i < count; i++) {
View view = drawer_list.getChildAt(i);
if (view != null) {
// create an Animation for each item
Animation animation = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);
animation.setDuration(300);
// ensure animation final state is "persistent"
animation.setFillAfter(true);
// calculate offset (bottom ones first, like in notification panel)
animation.setStartOffset(300 * (count - 1 - i));
// animation listener to execute action code
if (i == 0) {
animation.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
// NOT USED
}
public void onAnimationRepeat(Animation animation) {
// NOT USED
}
public void onAnimationEnd(Animation animation) {
// Clear table
notifications.flushNotificationTempTable_ActiveOnly();
// Update list adapter
refreshNotifications();
// Close drawer
notification_drawer.close();
}
});
}
view.startAnimation(animation);
}
}
The trouble spot is in the refreshNotifications() method when the line drawer_list.setAdapter(notificationAdapter); executes. I use this method and adapter all throughout my app and, as I said above, it works flawlessly without the animations.
I was able to solve this by eliminating the animation listener and adding a delayed runnable after it that ran my post animation code.
I was unable to find a way to set a new adapter (required because i used a custom adapter) inside the animation listener. If anyone knows how to do this I would like to know.