I have a Windows 8 app, and recently I refactored it to use a 'master page'. This means that there is one 'layout' that has a few generic components such as the header and footer. In that layout, I have a Frame. Every time I want to show a different view, I load it in the frame.
This means that my startup screen is no longer of type Frame but of type Layout, which is a LayoutAwarePage. This is how I initialize it in App.xaml.cs OnLaunched:
Layout rootFrame = Window.Current.Content as Layout;
if (rootFrame == null)
{
rootFrame = new Layout();
Here comes the problem: I have a charms flyout that contains a few items like Settings. I made a nice view (Flayouts.xaml) that contains the layout of these flyouts. The code behind for that view looks like this:
public Flyouts()
{
InitializeComponent();
SettingsPane.GetForCurrentView().CommandsRequested += Flyouts_CommandsRequested;
}
void Flyouts_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
// add some commands
}
And this is how you'd get this to work in your app:
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new CharmFlyoutLibrary.CharmFrame { CharmContent = new Flyouts() };
What they're doing here is assigning a Frame to 'rootFrame'. However, since I switched to a master page, I no longer have a Frame but a Layout/LayoutAwarePage type, so I can't assign the CharmFrame to it. How do I overcome this problem?
Anyone?
When navigating inside a frame the page that you navigate to is placed inside the navigate the Content property.
So if you navigate to you Layout first, then the content will be filled with your page and you can navigate to your child page's. I've placed a example below
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null) {
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
//Associate the frame with a SuspensionManager key
SuspensionManager.RegisterFrame(rootFrame, "AppFrame");
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated) {
// Restore the saved session state only when appropriate
try {
await SuspensionManager.RestoreAsync();
} catch (SuspensionManagerException) {
//Something went wrong restoring state.
//Assume there is no state and continue
}
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null) {
if (rootFrame.Navigate(typeof(Layout))) {
var secondFrame = rootFrame.Content as Layout;
if (!secondFrame.ContentFrame.Navigate(typeof(YourPage)) {
throw new Exception("Failed to create initial page");
}
}
}
Related
My game snapshot Attachment> Blockquote
My canvas constructs
public class DrawingView4 extends View{
DrawingView4(Context context4)
{
super(context4);
}
#Override protected void onDraw(Canvas canvas4)
{
int tile4=0;
if (DoneDrawFacilities && doneloading) {
}
else {
for (int i4=0; i4< 17 && notfixingorientation; i4++){
if (i4< 16) {
for (int ii4=0; ii4 < 16; ii4++){
try {
//Checking the data of all spots of the game map from package directory.
//Then Draw in canvas if the data of the spot occupied by type of human and core facilities,
FacilityList = new Gson().fromJson(FileUtil.readFile(FileUtil.getPackageDataDir(getApplicationContext()).concat("/GameResource/Tile".concat(String.valueOf((long)(tile4 + 1)).concat(".data")))), new TypeToken<ArrayList<HashMap<String, Object>>>(){}.getType());
if (FacilityList.get((int)0).get("Type").toString().equals("Human")) {
canvas4.drawBitmap(BitmapFactory.decodeFile(AllObjects.getString(String.valueOf((long)(tile4)), "")),null,new Rect(ii4*120, i4*120, 120*(ii4+1),120*(i4+1)), null);
}
if (FacilityList.get((int)0).get("Type").toString().equals("Core")) {
if (FacilityList.get((int)0).get("Name").toString().equals("Arena")) {
canvas4.drawBitmap(BitmapFactory.decodeFile(AllObjects.getString(String.valueOf((long)(tile4)), "")),null,new Rect(7*120, 7*120, 120*(8+1),120*(8+1)), null);
}
else {
}
}
} catch (Exception e) {
}
FacilityList.clear();
tile4++;
}
}
else {
DoneDrawFacilities = true;
}
}
}
}}
Blockquote
My Relocate button
//I use sharepreference called AllObjects rather than a list and I Only update the path of objects in specific tile in sharedpreference such as in variable 1, 2, etc. and then re-draw using this code below, next time I update the objects path and get this object path from the same json file in the package directory. Too decode to Bitmap and then Draw in canvas.
//Some other code are removed that just updating some data in specific file directory.
AA_structures_facilities.removeAllViews();
AA_structures_facilities.addView(new DrawingView4(GameActivity.this));
// But It freezes the screen or stop me from touching the touch event in a second everytime I update new canvas.
//WHILE MY touchevent is hundled in the parent LinearLayout where the canvas is placed.
I have a full screen RecyclerView which will have one invisible ViewHolder Item, like below
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
....
if (position == 6) {
viewHolder.itemView.setMinimumHeight(Resources.getSystem().getDisplayMetrics().heightPixels);
viewHolder.itemView.setVisibility(View.GONE);
viewHolder.setIsRecyclable(false);
}
...
}
Once the position 6 shows up on the screen, I can see the ImageView behind it and I'd like to be able to click on that. I have added an event handler to that ImageView but it is not being triggered. It seems RecyclerView is preventing the click event to bubble down. Is there any way to click a View thru invisible/gone RecyclerView ViewItem?
Since I asked the question, I have tried multiple techniques/methods which could/should pass the click/tap event down to the view hierarchy but nothing worked. The feature I was trying to build in the app was very complex and the app itself became very complicated overtime. Too many views on top of each other and global event handlers made the implementation harder.
So I have decided as last resort that to have an empty/transparent view holder in the RecyclerView which listens the click and touch events and based on the coordinates of the touch event, I fire different action. Here is the code:
private float[] lastTouchDownXY = new float[2];
public MyView getMyView(final Context context) {
MyView view = new MyView(context);
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
lastTouchDownXY[0] = motionEvent.getRawX();
lastTouchDownXY[1] = motionEvent.getRawY();
}
return false;
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final float x = lastTouchDownXY[0];
final float y = lastTouchDownXY[1];
int[] mLocButton = new int[2];
// mButton is the button in the background and visible thru transparent viewholder
mButton.getLocationOnScreen(mLocButton);
final int left = mLocButton[0];
final int top = mLocButton[1];
if (x > (left - mOffset) && x < (left + mOffset + mButtonWidth) &&
y > (top - mOffset) && y < (top + mOffset + mMuteUnmuteButtonHeight)) {
// mButton clicked
} else {
// entire view clicked except mButton clickable area
}
}
});
return view;
}
I'm working on Eclipse plugin and I add an 16x16 icon to the statusbar by
ToolBarManager manager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
manager.add(updatingNewsAction);
Where updatingNewsAction is a class that extends org.eclipse.jface.action.Action.
However I've got problem with removing the updatingNewsAction from the toolbar. It's removed, but I can see that only when something updates the statusbar - for example minimazing/maximazing the borderline views. Then after reading some blog post I've wrote:
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
IWorkbench wb = PlatformUI.getWorkbench();
IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
IWorkbenchPage page = win.getActivePage();
IWorkbenchPart part = page.getActivePart();
IWorkbenchPartSite site = part.getSite();
IViewSite vSite = (IViewSite) site;
IActionBars actionBars = vSite.getActionBars();
if (actionBars == null) {
return;
}
IStatusLineManager statusLineManager = actionBars.getStatusLineManager();
if (statusLineManager == null) {
return;
}
statusLineManager.update(true);
}
});
Which is a step forward, because it gets updated when switching focus between views, but still it doesn't happen immediately and without user interactions. How to update the status bar programmatically immediately?
I navigate between pages with Navigation Helper class which VS 2013 added when solution created, But scroll state most of controls (Like Pivot, Hub) does not saved like in Windows Phone 8.x Silverlight.
What should I do for implement this behaviour? Should I handle scrolling state by myself and restore scroll when i go back in visited page?
Thanks.
UPDATE1:
I need save selected pivot/hub item etc, when i go back to page.
UPDATE2:
void navigationHelper_SaveState(obj sender,SaveStateEventArgs e)
{
e.PageState["SelectedSection"] = MainHub.SectionsInView;
}
void navigationHelper_LoadState(obj sender,LoadStateEventArgs e)
{
if (e.PageState != null)
{
var sections = e.PageState["SelectedSection"] as IList<HubSection>;
if (sections != null && sections.Any())
MainHub.ScrollToSection(sections[0]);
}
}
On the page where you use the hub, set the navigation cache mode in constructor:
this.NavigationCacheMode = NavigationCacheMode.Enabled;
or in XAML:
<Page
x:Class="App.HubPage"
....
xmlns:data="using:App.Data"
NavigationCacheMode="Enabled"
....
Better use:
this.NavigationCacheMode = NavigationCacheMode.Required;
before:
this.InitializeComponent();
And add:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
this.NavigationCacheMode = NavigationCacheMode.Disabled;
}
to remove cache on back navigation from page.
I have a custom sitecore button which changes the template of the current item, simple enough.
However as part of this I'm trying to also migrate the renderings of the old layout to a new layout if it's of a certain sublayout type by ItemId. However the ItemId that is returned is always null, the only value I get back from the RenderingDefinition is the UniqueId.
What am I doing wrong?
I have used this blog post as a guide.
The Code
public class ConvertToNewTemplateCommand : Command
{
protected void Run(ClientPipelineArgs args)
{
if (!SheerResponse.CheckModified())
return;
Item item = Context.ContentDatabase.Items[args.Parameters["id"]];
if (args.IsPostBack)
{
if (args.Result == "yes")
{
//Get current layout details
var originalLayoutXml = item[FieldIDs.LayoutField];
//Get new template
TemplateItem hubTemplate = Context.ContentDatabase.GetTemplate("some guid...");
//Change template
item.ChangeTemplate(hubTemplate);
//Reset laytout
ResetLayout(item);
//Get reset layout
var newLayoutXml = item[FieldIDs.LayoutField];
//Add all the module containers to the new layout in the central column
MoveModuleContainers(item, originalLayoutXml, newLayoutXml);
}
}
}
private void MoveModuleContainers(Item item, string oldXml, string newXml)
{
var oldLayout = LayoutDefinition.Parse(oldXml);
var newLayout = LayoutDefinition.Parse(newXml);
bool updated = false;
var oldRenderings = (oldLayout.Devices[0] as DeviceDefinition).Renderings;
var newRenderings = (newLayout.Devices[0] as DeviceDefinition).Renderings;
foreach (RenderingDefinition rendering in oldRenderings)
{
// Here is where the rendering.ItemID is always null
if (rendering != null && !String.IsNullOrEmpty(rendering.ItemID) && new Guid(rendering.ItemID) == new Guid("matching guid..."))
{
rendering.Placeholder = "middlecolumn";
newRenderings.Add(rendering);
updated = true;
}
}
if (updated)
{
// Save item...
}
}
}
I got onto Sitecore support in the end which informed me that I should use:
Sitecore.Data.Fields.LayoutField.GetFieldValue(item.Fields[Sitecore.FieldIDs.LayoutField])
instead of:
item[FieldIDs.LayoutField]
to get the items layoutField correctly. This results in the rendering values being parsed correctly and as they say the rest is history.