I can only find solutions to this for the case of using the support library.
Facts:
build.gradle:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:design:22.2.0'
}
menu_main.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="#+id/ab_main_share"
android:showAsAction="ifRoom|withText"
android:title="Share"
android:icon="#drawable/ic_settings_input_antenna_black_24dp"
android:actionProviderClass=
"android.widget.ShareActionProvider" />
<item
android:id="#+id/ab_main_delete"
android:showAsAction="ifRoom|withText"
android:title="Delete"
android:icon="#drawable/ic_delete_black_24dp" />
<item android:id="#+id/action_settings" android:title="#string/action_settings"
android:orderInCategory="100" app:showAsAction="never" />
</menu>
MainActivity.java:
public class MainActivity extends Activity {
private ShareActionProvider mShareActionProvider;
...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate menu resource file.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
/** Getting the actionprovider associated with the menu item whose id is share */
mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.ab_main_share).getActionProvider();
/** Setting a share intent */
mShareActionProvider.setShareIntent(getDefaultShareIntent());
return super.onCreateOptionsMenu(menu);
}
And the result is that the actions appear in the overflow. I tried also to put just one action, but I get the same result. So it's not a problem of not having room in the action bar (and the name of the app or the application icon is not so wide).
Am I missing something? I did these thing before with the support library and had no problems, but this app is minSdkVersion 17, so there's no reason to use it anymore.
Found it! The problem was in the Manifest. I had this in the activity declaration:
android:theme="#android:style/Theme.Holo.Light.Dialog"
Removed it and now I can see the action buttons in the action bar.
Related
I have just updated my code to use the latest 2.4.0-alpha05 for the navigation component and I have custom navigation between the multiple stacks and my main nav graph is like the documentation I found.
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:startDestination="#+id/accounts"
android:id="#+id/bottom_nav">
<inclue app:graph="#navigation/accounts_tab_nav"/>
<include app:graph="#navigation/contact_tab_nav" />
<include app:graph="#navigation/profile_tab_nav" />
</navigation>
Most of my stacks animate with a slide from right to left. It looks like that when I am on the second screen, in let's say the profile screen, and then switch to the first tab it triggers the popEnter en popExitAnim that are defined in the action that leads to the second screen in the profile tab. Like so:
<fragment
android:id="#+id/profileMain"
android:name="com.app.ProfileFragment"
tools:layout="#layout/fragment_profile">
<action
android:id="#+id/action_profileMain_to_secondFragment"
app:destination="#id/secondFragment"
app:enterAnim="#anim/slide_in_right"
app:exitAnim="#anim/slide_out_left"
app:popEnterAnim="#anim/slide_in_left"
app:popExitAnim="#anim/slide_out_right" />
</fragment>
But obviously I want tho use the (default) fade animation when switching tabs. So how should I do that?
And I would like to pop to the root of the stack when reselecting a tab. But I probably have to do that myself?
I came up with a solution that seems to work for me, but I have to admit it feels a little bit hacky.
I have a public flag in my MainActivity:
var tabWasSelected = false
Then I remember if a tab item was selected in setOnItemSelectedListener
// always show selected Bottom Navigation item as selected (return true)
bottomNavigationView.setOnItemSelectedListener { item ->
// In order to get the expected behavior, you have to call default Navigation method manually
NavigationUI.onNavDestinationSelected(item, navController)
// set flag so that the fragment can call the correct animation on tab change in onCreateAnimation
tabWasSelected = true
return#setOnItemSelectedListener true
}
This will always select the item and navigate to the associated destination while maintaining multiple back stacks.
I then have created a Fragment class which all my other fragments inherit from. It simply overrides onCreateAnimation to set the correct animation. Here is what it looks like:
open class MyFragment: Fragment() {
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
val activity = requireActivity()
if (activity is MainActivity) {
if (activity.tabWasSelected) {
if (enter) {
//flow is exit first, then enter, so we have to reset the flag on enter
//in order that following animations will run as defined in the nav graph
activity.tabWasSelected = false
return AnimationUtils.loadAnimation(requireContext(), R.anim.nav_default_pop_enter_anim)
} else {
return AnimationUtils.loadAnimation(requireContext(), R.anim.nav_default_pop_exit_anim)
}
}
}
//no tab was selected, so run the defined animation
return super.onCreateAnimation(transit, enter, nextAnim)
}
}
Instead of using setupWithNavController function, follow this way.
First, create your NavOptions which include animation shown below.
val options = NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.enter_from_bottom)
.setExitAnim(R.anim.exit_to_top)
.setPopEnterAnim(R.anim.enter_from_top)
.setPopExitAnim(R.anim.exit_to_bottom)
.setPopUpTo(navController.graph.startDestination,false)
.build();
Then use setOnNavigationItemSelectedListener to navigate with animation like that.
bottomNavigationView.setOnNavigationItemSelectedListener
{ item ->
when(item.itemId) {
R.id.fragmentFirst -> {
navController.navigate(R.id.fragmentFirst,null,options)
}
R.id.fragmentSecond -> {
navigate(R.id.fragmentSecond,null,options)
}
R.id.fragmentThird -> {
navController.navigate(R.id.fragmentThird,null,options)
}
}
}
Finally, you should prevent same item selection case so you can add below code.
bottomNavigationView.setOnNavigationItemReselectedListener
{ item ->
return#setOnNavigationItemReselectedListener
}
I used bottomNavigation like that in my project to add animation for page transitions. I hope it helped.
I'm new to UWP and I have what I think is a simple problem to solve, but the examples I've found haven't worked. I'm using a navigation view in UWP project and I want to be able to switch page and display in a frame. When I select an item in the navigation view the ItemInvoked event is fired. I know the code to load the page into the frame which I've included below.
void enVigilServer::MainPage::nvSample_ItemInvoked(Windows::UI::Xaml::Controls::NavigationView^ sender, Windows::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs^ args)
{
this->contentFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(SysConf::typeid));
}
My problem is how to determine which item I've selected from the NavigationView to show the relevant page.
Thanks
It's actually related to c++-cx and I will purpose this tag to your issue.
To make the navigation simple we can use the tag system in our app. See the following code:
<NavigationView x:Name="NavigationViewControl" ItemInvoked="NavigationViewControl_ItemInvoked" >
<NavigationView.MenuItems>
<NavigationViewItem Content="A" x:Name="A" Tag="tga" />
<NavigationViewItem Content="B" x:Name="B" Tag="tgb"/>
<NavigationViewItem Content="C" x:Name="C" />
</NavigationView.MenuItems>
<Frame x:Name="contentFrame"/>
</NavigationView>
This is an example, we will add tags to our items. Then we will do the following in our invoke code:
void NavigationVWCX::MainPage::NavigationViewControl_ItemInvoked(Windows::UI::Xaml::Controls::NavigationView^ sender, Windows::UI::Xaml::Controls::NavigationViewItemInvokedEventArgs^ args)
{
auto navitemtag = args->InvokedItemContainer->Tag->ToString();
if (navitemtag == "tga")
{
contentFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(PageA::typeid));
}
if (navitemtag == "tgb")
{
contentFrame->Navigate(Windows::UI::Xaml::Interop::TypeName(PageB::typeid));
}
}
BTW, don't forget to also add tag to your pages, like:
PageB::PageB()
{
InitializeComponent();
this->Tag = "tgb";
}
Steps, I have used to create my first Google Glass GDK App
New Project > Application name, company domain > Next > Glass (Glass Development Kit Preview (Google Inc.) (API 19)) > Next > Immersion Activity
ImmersionActivity.java:
public class ImmersionActivity extends Activity {
/**
* {#link CardScrollView} to use as the main content view.
*/
private CardScrollView mCardScroller;
private View mView;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
mView = buildView();
mCardScroller = new CardScrollView(this);
mCardScroller.setAdapter(new CardScrollAdapter() {
#Override
public int getCount() {
return 1;
}
#Override
public Object getItem(int position) {
return mView;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
return mView;
}
#Override
public int getPosition(Object item) {
if (mView.equals(item)) {
return 0;
}
return AdapterView.INVALID_POSITION;
}
});
// Handle the TAP event.
mCardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Plays disallowed sound to indicate that TAP actions are not supported.
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
am.playSoundEffect(Sounds.DISALLOWED);
}
});
setContentView(mCardScroller);
}
#Override
protected void onResume() {
super.onResume();
mCardScroller.activate();
}
#Override
protected void onPause() {
mCardScroller.deactivate();
super.onPause();
}
/**
* Builds a Glass styled "Hello World!" view using the {#link CardBuilder} class.
*/
private View buildView() {
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
card.setText(R.string.hello_world);
return card.getView();
}
}
Manifest.xml:
<activity
android:name=".ImmersionActivity"
android:icon="#drawable/ic_glass_logo"
android:label="#string/title_activity_immersion" >
<intent-filter>
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
</intent-filter>
<meta-data
android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/voice_trigger" />
</activity>
voice_trigger.xml:
<trigger command="SHOW_ME_A_DEMO" />
Now, what i have understood, we can run this app by trigger voice command "SHOW ME A DEMO", Is that right or wrong ?
And is there any way to run Glass GDK app on Android Emulator using Android Studio ?
Now, what i have understood, we can run this app by trigger voice command "SHOW ME A DEMO", Is that right or wrong ?
It's correct. YOu can even configure this trigger and use other commands.
And is there any way to run Glass GDK app on Android Emulator using Android Studio ?
No you can't. Only Tablet, Phone, Wear (watches) and TV devices are available on the Android Virtual Device Manager.
Now, what i have understood, we can run this app by trigger voice command "SHOW ME A DEMO", Is that right or wrong ?
yes you could run a app with the trigger set as command = "Show_me_a_demo"
But with this you are only able to run it from the speak menu.
I would turn it into
<trigger keyword="#string/app_name"/>
you could use any keyword you want but with this it would show up in the application menu as well as on the speak menu. The name that would show would be whatever you named your app.
It would also be a good idea to add <uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
to your manifest. To make sure the custom commands work
there are no emulators for the glass available as of now.
In a Windows 8 Metro app, is it possible to create a ScrollViewer which upon reaching the last item in the view, it loops back to the first item in the view? If so, how can I achieve this effect?
It is definitely possible. I am solving the problem at the moment and will post work when done. So far it goes something like below.
THe idea is that you hook into the viewchanged event for the scroll viewer, which fires anytime you move the bar. Once there, calculate where you are in the offset and the size of your items, and then you can use that to measure against the actual size of your listbox container or what have you.
Once you know where you are in the offset and know the actual height of your listbox and the height of your items, you know which items are currently visible and which are not. Make sure your list bound to the object is an observable collection implementing the INotifyChanged interface with two way binding. Then you can define a set of objects to rotate back and forth based on where in the scrolling you are.
Another option is to try a different starting point, perhaps a single control with a marquee and a scrollbar under it?
XAML
</UserControl.Resources>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="ScrollViewer1">
<ListBox x:Name="SampleListBox" Background="White" ItemsSource="{Binding Path=sampleItems}" ItemTemplate="{StaticResource sampleTemplate}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.Row="0" Grid.RowSpan="2">
</ListBox>
</ScrollViewer>
</Grid>
Code Behind
public sealed partial class MainPage : Page
{
List<SampleItem> sampleItems;
const int numItems = 15;
public MainPage()
{
sampleItems = new List<SampleItem>();
for (int i = 0; i < numItems; i++)
{
sampleItems.Add(new SampleItem(i));
}
this.InitializeComponent();
SampleListBox.ItemsSource = sampleItems;
ScrollViewer1.ViewChanged += ScrollViewer1_ViewChanged;
}
void ScrollViewer1_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
ScrollViewer viewer = sender as ScrollViewer;
ListBox box = viewer.Content as ListBox;
ListBoxItem lbi = box.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
double elementSize;
if (lbi == null)
return;
elementSize = lbi.ActualHeight;
} /// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached. The Parameter
/// property is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
public class SampleItem
{
public String ItemCount { get; set; }
public SampleItem(int itemCount)
{
ItemCount = itemCount.ToString();
}
}
I don't believe there is a control like that in WinRT/XAML, so you would need to implement a custom control. There are many approaches you could take, but I would probably avoid using the ScrollViewer and handle manipulation events directly since it might not be easy to bend ScrollViewer's behavior to your requirements. I would control the scroll offset based on the manipulation events and based on the scroll offset - position the elements in the view - e.g. using a Canvas control. You would need to reposition elements in the items panel depending on a scroll offset, so that for example items that go beyond the view port on one end are moved to the other end. It would involve custom dependency properties, item containers etc. Probably at least a few hours of work if you know all these APIs.
I'm working on a project that uses a master page and content pages. My masterpage a navigation bar:
<asp:Menu ID="NavigationMenu" runat="server" CssClass="menu" EnableViewState="false" IncludeStyleBlock="false" Orientation="Horizontal">
<Items>
<asp:MenuItem NavigateUrl="~/ProjectPage.aspx" Text="Home" />
<asp:MenuItem NavigateUrl="~/ProductBacklog.aspx" Text="Product Backlog"/>
<asp:MenuItem NavigateUrl="~/SprintBacklog.aspx" Text="Sprint Backlog" />
<asp:MenuItem NavigateUrl="~/MeetingPage.aspx" Text="Meetings" />
<asp:MenuItem NavigateUrl="~/Burndown.aspx" Text="Burndown"/>
<asp:MenuItem NavigateUrl="~/About.aspx" Text="About Us"/>
</Items>
</asp:Menu>
On one of my content pages, I dynamically add sub-menu menuitems to my 'Sprint Backlog' menuitem. There is a button, and everytime the user clicks that button, a sub-menuitem is added, so that when the user hovers over 'Sprint Backlog' in the navigation menu, the submenu comes up. I do this by creating a list of menuitems, creating a new menuitem with (shown text, value, navigationURL), adding the menuitem to the list of menuitems, then saving the list to Session:
protected void btSave_Click(object sender, EventArgs e)
{
menuItemList = (List<MenuItem>)Session["menuItemList"];
if (menuItemList == null)
{
menuItemList = new List<MenuItem>();
}
MenuItem menuItem = new MenuItem("Sprint " + sprintNumber, sprintNumber.ToString(), "SprintBacklog.aspx");
menuItemList.Add(menuItem);
Session["menuItemList"] = menuItemList;
}
In the code-behind for my masterpage, I create a list of menuitems, set the value of the instance of the menuitem from Session, and add childitems to the navigationmenu at the appropriate index. The childitem I am adding are the menuitems from the list of menuitems.
List<MenuItem> menuItemList;
protected void Page_Load(object sender, EventArgs e)
{
menuItemList = (List<MenuItem>)Session["menuItemList"];
if (menuItemList != null)
{
foreach (MenuItem menuitem in menuItemList)
{
NavigationMenu.Items[2].ChildItems.Add(menuitem);
}
}
}
I know that I gave these childitems a value when I created them, but my problem is accessing those values when I am loading the SprintBacklog.aspx content page. Whenever a user clicks on one of the childitems, it will always navigate to SprintBacklog.aspx, but the contents of that page should differ according to which child item they clicked. I need a way to know which childitem they clicked, and access that value to populate my content page.
If someone has a better way for me to carry this whole thing out, I am open for suggestions and change. Otherwise, if my setup can work, and there is a way for me to extract the value of the clicked childitem, I'd really like to know that.
I know if I hard-code the childitems in my masterpage, I can easily get the value, but my problem is that I'm creating the submenu childitems dynamically, and I'm not sure how to access it.
Any help would be really appreciated! Thanks!
-Jose
It's been a long time since I asked this question, and I'm not familiar with how masterpages work anymore, but if anyone is experiencing anything similar, I may have a suggestion.
Each menu item I was creating was linking to SprintBacklog.aspx like so:
MenuItem menuItem = new MenuItem("Sprint " + sprintNumber, sprintNumber.ToString(), "SprintBacklog.aspx");
What I should have done was link to SprintBacklog.aspx, but also add a parameter to the request with the sprint ID.
Then the controller which handles the rendering of SprintBacklog.aspx would read the parameter and fetch the appropriate data to render.