Can we provide the navigation to different parts of a single image - android

We are developing an Android application where the requirement is to have single image having different navigation when the different parts of the image are clicked. E.g. A full image of a building and clicking on the different flats we want to show the amenities offered in the flat ( build up area, number of rooms, number of balconies, terrace (if pent house) etc).
Have thought the following two possibilities,
Slice the images and put together (such that it look as a single image) in layout xml, once user clicks it, with the image view id we will know which portion is clicked.
Slice the images and put together (such that it look as a single image) in html with onclick event, load the html in webview, create JavaScript class that handles clicks.
With above two it is difficult because the parts are not proper rectangle or square shaped.
ASP.Net has ImageMap control for this purpose, do we have anything of that sort in Android?

There is no such component to do this in android, but you can easily create one:
public class ImageMap extends ImageView implements onClickListener
{
List<Rect> hotspot;
public ImageMap(Context c)
{
super(c);
hotspot = new List<Rect>();
setOnClickListener(this);
}
public void addHotSpot(Rect r)
{
hotspots.add(r);
}
public void onClick(Event e)
{
int currentPosition = 0;
for(Rect spot : hotspot){
if(spot.contains(e.getX(), e.getY()))
triggerClickInHotSpotAtPos(currentPosition);
currentPosition ++;
}
}
public void triggerHotSpot(int hotspotIndex)
{
//TODO do something useful like calling listener for this given hotspot etc ...
}
}
be aware that is not a finished work, but its more like pseudo code, the important is you got the idea.

You could do this with a single ImageView by tapping into its onTouch event handler.
See the MotionEvent documentation for specifics on how to get coordinates of the touch event.

Related

Android partially active Activity

I have an activity A. I am creating a kind of tutorial for user for this activity, to teach him how he can use the app on that screen.
For that, my requirement is :
I want to blur all the views of the activity except one view. I want to prompt user to click on that view through a hand image pointing at that view.
Nothing should happen if the user clicks on the blurred/greyed out area, but if he taps on that particular active view, it should react to that touch.
I was thinking of using a full screen fragment for this. The Fragment will take the following input from the activity :
for what coordinates, is should not blur the screen and pass the touch event to the activity
the coordinates on which it should show that pointing hand image.
After from these coordinates, the fragment background would be blur.
I wanted to confirm if that's possible, to make the fragment partially active, i.e. delegate it's touch events to the activity for a particular view of the activity.
Also, please let me know if there is any other better approach of achieving the same thing.
Edit1 :
Thinking of using a fragment here, because I'd want this type of behaviour on different screen in future. In that case, I'd make that fragment generic which takes some inputs (as described above) and use it on different screens.
There's a very good library called SCV which does what you're trying to achieve, you're able to customize the styles for it too. I've used this for first time the app is opened to show the user a tutorial.
According to their Github
The ShowcaseView (SCV) library is designed to highlight and showcase specific parts of apps to the user with a distinctive and attractive overlay. This library is great for pointing out points of interest for users, gestures, or obscure but useful items.
Further Reading:
Android Arsenal - Showcase Views Tutorial
ShowCaseView on Android - Indipendev
I found it much easier to include an 'extra' layout around the UI of my activity, and then to add a highest-z grey mostly-transparent filter to it and put the instructions on that.
Each "step" of the instructions was a different layout that was dynamically loaded into that layout container as they clicked. (Just another approach)
The 'container' layout is a: FrameLayout
then in my Activity I have: (ignore bad naming)
private void addOverlayLayout() {
frameLayout = (FrameLayout) findViewById(R.id.framelayoutInner);
frameLayout3 = (FrameLayout) findViewById(R.id.framelayout3);
frameLayout3.setBackgroundColor(Color.DKGRAY);
frameLayout3.setAlpha(0.3f);
// Dynamically create a relativelayout which will be appended to framelayout
relativeLayout = new RelativeLayout(getApplicationContext());
relativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams
.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
instructionOverlays.add(createSimpleClickInstruction(R.layout.instruction_reader_1));
instructionOverlays.add(createSimpleClickInstruction(R.layout.instruction_reader_2));
if (FullscreenReaderActivity.isFirstRun) {
displayNextGuide();
}
}
public void displayNextGuide() {
// clean relative layout if it has views
relativeLayout.removeAllViews();
// clean frame layout if it has child (safe if empty)
frameLayout.removeView(relativeLayout);
if (!isFirstRun) {
return;
}
if (instructionOverlays.size() > 0) {
runOnUiThread(instructionOverlays.get(0));
instructionOverlays.remove(0);
} else {
frameLayout3.setBackgroundColor(Color.TRANSPARENT);
frameLayout3.setAlpha(1.0f);
}
}
public Runnable createSimpleClickInstruction(final int resource) {
return new Runnable() {
#Override
public void run() {
getLayoutInflater().inflate(
resource,
relativeLayout,
true
);
relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
displayNextGuide();
}
});
frameLayout.addView(relativeLayout);
}
};
}

What is the best way to handle multiple "add" screens

I am making an android app, using Xamarin, that allows a user to add and then view various types of information. Currently I made an 'add item' screen for each type of information the user is able to store but that is currently 11 screens and when I add the display views then that is 11 more. Eventually that could grow to even more. Is there a better way to handle this sort of thing?
More Detail:
To do a very simple example using 2 items, lets say a user can store the following information about a Car:
Exterior Color
Interior Color
Amount of Doors.
Then lets say the user can store the following about a Building:
Amt of Floors
Address
Phone Number
For the car 'add item' screen I would want textviews and plainviews for each of that information and then lets say I would want a box at the bottom to allow a user to upload an image. Then for the building 'add item' screen i want to have, again, textviews and plainviews for each piece of information but this time I want there to be a box for notes at the bottom instead.
Again this is a simple example. In reality the screens look pretty different overall but serve the same functionality in the sense that they allow a user to add information, but that information is also much different then each other for the most part.
TLDR: What is the best way to handle screens that serve the same relative purpose but look differently? Do I make separate activities and layouts for each add screen or is there a way to use a master layout/activity that changes based on the type of item being added?
PS: I do not think using Xamarin plays any part in this but I wanted to mention it to be safe.
What is the best way to handle screens that serve the same relative purpose but look differently?
Abstract out the same part of the layouts. For example Both your "car" and "Building" layout should have "upload image" mode. when you design this kind of layout. You can use <include> tag as follows
<include
layout="#layout/upload_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Dynamic layout is also suitable for you. For example both "car" and "Building" layout need some textView, your can write as following code:
public class DynamicLayout : LinearLayout
{
private List<LinearLayout> layouts;
public DynamicLayout(Context context, int textViewcount) : base(context)
{
this.Initialize(textViewcount);
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
base.OnSizeChanged(w, h, oldw, oldh);
foreach (var l in layouts)
{
l.LayoutParameters = new LinearLayout.LayoutParams(w / layouts.Count, ViewGroup.LayoutParams.WrapContent);
}
}
private void Initialize(int textViewcount)
{
this.Orientation = Orientation.Horizontal;
layouts = new List<LinearLayout>();
for (int n = 0; n < textViewcount; n++)
{
var layout = new LinearLayout(this.Context)
{
Orientation = Orientation.Vertical,
LayoutParameters =
new LinearLayout.LayoutParams(this.Width / textViewcount, ViewGroup.LayoutParams.WrapContent)
};
layouts.Add(layout);
if ("car")
{
var textView = new TextView(this.Context)
{
Text = "Car"
};
layout.AddView(textView);
}
else if ("building")
{
var textView = new TextView(this.Context)
{
Text = "building"
};
layout.AddView(textView);
}
this.AddView(layout);
}
}
}
But Dynamic layout is hard to control the display of the views. If the two methods are used in combination that could be better.

Get model object from ImageTarget Android

Currently, i'm trying to work with augment reality in android. For this task i'm using Unity + Vuforia.
So, i have made a scene, which is working, when i'm looking to specific object from my camera it shows me my model(basically 3d cat model with animation). I've done this according to tutorials like this:
text format tutorial and videos on youtube like this : video tutroial.
After this i've made android application, based on this scene, like this:
The result is Android project, which basically has one Activity and banch of assets and libs. The only connection with Unity that i see so far is UnityPlayer class, but it's just a ViewGroup, extended from FrameLayout
public class UnityPlayer extends FrameLayout implements com.unity3d.player.a.a
My goal: I need to overrideonClick on the view from Unity, which i've created(my 3d cat), something like when you click on cat on your phone, it will make some sound, and set some animation to it on after clicking. I have a model on the scene, just logically it has been converted to View class inside of Android, and i thought that it's just a child of UnityPlayer, but code like this :
mUnityPlayer.getChildAt(0).setOnClickListener
has no effect.
I want either have some object which will contain all the animations and other properties which model in unity has, or if it's impossible, learn how to set onClick listeners in Unity itself
I realize that this question might be unclear, and i would like to explain it in more details for those who would try to help.
If you need more info, just ask for it in comments. Thanks
Edit: As answer was suggesting, i could simply write a script for this, which i did, for using VirtualButton, it looks like this:
using UnityEngine;
using System.Collections.Generic;
using Vuforia;
public class VirtualButtonEventHandler : MonoBehaviour, IVirtualButtonEventHandler {
// Private fields to store the models
private GameObject kitten;
private GameObject btn;
/// Called when the scene is loaded
void Start() {
// Search for all Children from this ImageTarget with type VirtualButtonBehaviour
VirtualButtonBehaviour[] vbs = GetComponentsInChildren<VirtualButtonBehaviour>();
for (int i = 0; i < vbs.Length; ++i) {
// Register with the virtual buttons TrackableBehaviour
vbs[i].RegisterEventHandler(this);
}
// Find the models based on the names in the Hierarchy
kitten = transform.FindChild("kitten").gameObject;
btn = transform.FindChild("btn").gameObject;
kitten.SetActive(false);
btn.SetActive(true);
}
/// <summary>
/// Called when the virtual button has just been pressed:
/// </summary>
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb) {
//Debug.Log(vb.VirtualButtonName);
//GUI.Label(new Rect(0, 0, 10, 5), "Hello World!");
}
/// Called when the virtual button has just been released:
public void OnButtonReleased(VirtualButtonAbstractBehaviour vb) {
}
}
As you can see, in Start() method i want to find and hide model, which called kitten, but it's not hiding
I've attached this script to virtual button object, i will provide a screen:
Edit: My mistake actually, for some reason, i had to attach VirtualButtonBehaviorHandler script to an ImageTarget, it's not that simple to understand for me, but i think i see some logic behind it right now.
But, for some unknow reason, if i'm adding this code:
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb) {
//Debug.Log(vb.VirtualButtonName);
switch(vb.VirtualButtonName) {
case "btn":
kitten.setActive(true);
break;
}
}
It works instantly, even without touching on the button
Final edit: This was happenning, because i've add my button in database .xml, when i've removed button from it - everything worked, i'm marking the only one answer as correct, because it helped me
Brother Everything is possible if we do it. As per my understanding , what exactly you want to do is :
First : You need to clear some basic concept by reading blog & Tutorials:
As you mentioned object on which your white cyte :) cat render is "Marker"
In Unity Everything is gameobject you can write script to manipulate that gameobject (CAT) using script. which will be in either C#(Mono) or JavaScript for this work you can use Visual Studio or MonoDevelop by Unity
But before that please search for keywords on google
a) Touchevent, RayCastMenu Controle in unity: To handle Touch
b) MonoBehaviour class, Start() , Update(), OnGUI() method in Unity
You can identify any gameObject by using its name or Tag which you can see or change in Inspector window
These are some basic things . Please follow vuforia developer portal to learn more:
https://developer.vuforia.com/library/
Now: Coming to your question:
According to me you wanna do some stuff on Click of your sweet cat .
Its simple, if simply you want to launch android activity on click of cat then there are 2 possible ways:
Create android project and import it in unity as Library project in Unity.
OR
create android activity from unity project with the help of C# script. Attach this script to any GameObject in scene.
Here I providing the example of second one : On click of Button It will launch Android Activity.
What you have to do is:
Replace Button GameObject By CAT GameObjectExport Project as Android and write activity with same name and package as mention in C# code to do whatever you want to
Here In my example I have explained:
How to popup GUI when Marker is detected using Unity+ Vuforia
How to launch android Activity from Unity Code on Specific event
How to handle Event in Unity
How to maintain GUI same with multiple Resolutions
Please Study code Carefully and read the comments also :)
using UnityEngine;
using System.Collections;
using Vuforia; //import Vuforia
using System;
public class ButtonPopup : MonoBehaviour, ITrackableEventHandler
{
float native_width= 1920f;// Native Resolution to maintain resolution on different screen size
float native_height= 1080f;
public Texture btntexture;// drag and drop any texture in inspector window
private TrackableBehaviour mTrackableBehaviour;
private bool mShowGUIButton = false;
void Start () {
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if (mTrackableBehaviour) {
mTrackableBehaviour.RegisterTrackableEventHandler(this);
}
}
public void OnTrackableStateChanged(
TrackableBehaviour.Status previousStatus,
TrackableBehaviour.Status newStatus)
{
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
mShowGUIButton = true;// Button Shown only when marker detected same as your cat
}
else
{
mShowGUIButton = false;
}
}
void OnGUI() {
//set up scaling
float rx = Screen.width / native_width;
float ry = Screen.height / native_height;
GUI.matrix = Matrix4x4.TRS (new Vector3(0, 0, 0), Quaternion.identity, new Vector3 (rx, ry, 1));
Rect mButtonRect = new Rect(1920-215,5,210,110);
if (!btntexture) // This is the button that triggers AR and UI camera On/Off
{
Debug.LogError("Please assign a texture on the inspector");
return;
}
if (mShowGUIButton) {
// different screen position for your reference
//GUI.Box (new Rect (0,0,100,50), "Top-left");
//GUI.Box (new Rect (1920 - 100,0,100,50), "Top-right");
//GUI.Box (new Rect (0,1080- 50,100,50), "Bottom-left");
//GUI.Box (new Rect (Screen.width - 100,Screen.height - 50,100,50), "Bottom right");
// draw the GUI button
if (GUI.Button(mButtonRect, btntexture)) {
// do something on button click
OpenVideoActivity();
}
}
}
public void OpenVideoActivity()
{
var androidJC = new AndroidJavaClass("com.unity3d.player.UnityPlayer”);// any package name maintain same in android studio
var jo = androidJC.GetStatic<AndroidJavaObject>("currentActivity");
// Accessing the class to call a static method on it
var jc = new AndroidJavaClass("com.mobiliya.gepoc.StartVideoActivity”);//Name of android activity
// Calling a Call method to which the current activity is passed
jc.CallStatic("Call", jo);
}
}
Remember : In Unity everything is GameObject and you can write script to manipulate any GameObject
Edit: Info for Virtual Button
Virtual Buttons detect when underlying features of the target image are obscured from the camera view. You will need to place your button over an area of the image that is rich in features in order for it to reliably fire its OnButtonPressed event. To determine where these features are in your image, use the Show Features link for your image in the Target Manager.
Choose areas in the images that have dimensions of approximately 10% of the image target’s size.
Here is example in image i have simplify for you:
Register the Virtual Button:
To add a virtual button to an image target, add the VirtualButton element and its attributes to the ImageTarget element in the .xml file.
XML Attributes:
Name - a unique name for the button
Rectangle - defined by the four corners of the rectangle in the
target's coordinate space
Enabled - a boolean indicating whether the button should be enabled
by default
Sensitivity - HIGH, MEDIUM, LOW sensitivity to occlusion
You can get .Xml file in streamingAsset folder in unity project .
<ImageTarget size="247 173" name="wood">
<VirtualButton name="red" sensitivity="HIGH" rectangle="-108.68 -53.52 -75.75 -65.87"
enabled="true" />
<VirtualButton name="blue" sensitivity="LOW" rectangle="-45.28 -53.52 -12.35 -65.87"
enabled="true" />
<VirtualButton name="yellow" sensitivity="MEDIUM" rectangle="14.82 -53.52 47.75 -65.87"
enabled="true" />
<VirtualButton name="green" rectangle="76.57 -53.52 109.50 -65.87"
enabled="true" />
</ImageTarget>
After Registering Virtual Button Code is simple then:
public class Custom_VirtualButton : MonoBehaviour, IVirtualButtonEventHandler
{
// Use this for initialization
void Start () {
// here it finds any VirtualButton Attached to the ImageTarget and register it's event handler and in the
//OnButtonPressed and OnButtonReleased methods you can handle different buttons Click state
//via "vb.VirtualButtonName" variable and do some really awesome stuff with it.
VirtualButtonBehaviour[] vbs = GetComponentsInChildren<VirtualButtonBehaviour>();
foreach (VirtualButtonBehaviour item in vbs)
{
item.RegisterEventHandler(this);
}
}
// Update is called once per frame
void Update () {
}
#region VirtualButton
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb)
{
Debug.Log("Helllllloooooooooo");
}
public void OnButtonReleased(VirtualButtonAbstractBehaviour vb)
{
Debug.Log("Goooooodbyeeee");
}
#endregion //VirtualButton
}
and after writing this code you have to go to StreamingAsset/QCAR and find your ImageTarget XML Association & do something like this:
<?xml version="1.0" encoding="UTF-8"?>
<QCARConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="qcar_config.xsd">
<Tracking>
<ImageTarget name="marker01" size="100.000000 100.000000">
<VirtualButton name="red" rectangle="-49.00 -9.80 -18.82 -40.07" enabled="true" />
</ImageTarget>
</Tracking>
</QCARConfig>
Best of Luck :) Bdw CAT is so cute:)

How to know a user as moved to a new Card in a Google Glass app?

Is there a way for the CardScrollView or CardScrollAdapter to let me know when the user moves from one card to another?
Initially I was using the GestureDetector to detect swipes to the left or right, but in Glass applications users can use, e.g., two-finger swipes to quickly pan and move to a distant card (or even voice controls).
There must be a better way to know exactly when a new card is displayed than to track all these directional events.
I know CardScrollView.getSelectedItemPosition() gives me the current card in view, but not exactly when a new card is displayed.
I also thought that CardScrollAdapter.getView() would run every time a new card is displayed, but in Glass applications it runs once in the beginning of the activity execution.
Any help would be great.
My Glass is somewhere in my storage so I can't test this now but you can try onDetachedToWindow and onAttachedToWindow. Probably something like this:
private View buildView() {
CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT);
card.setText(R.string.whatever);
View view = card.getView();
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
#Override
public void onViewAttachedToWindow(View v) {
}
#Override
public void onViewDetachedFromWindow(View v) {
}
});
return view;
}
Also Card lifecycle might give you some idea.
The solution is actually in the documentation as suggested by #EntryLevelDev
CardScrollView notifies you with the following listener interfaces that are inherited from AdapterView:
AdapterView.OnItemSelectedListener - An item is selected after the user finishes scrolling through the list and settles on an item.
from: https://developers.google.com/glass/develop/gdk/reference/com/google/android/glass/widget/CardScrollView#onAttachedToWindow()

Moving between "pages" ( CCLayer ) in cocos2dx

I have 2 MyGameScreen objects that extends cocos2d::CCLayer. I am capturing the ccTouchesMove of the first screen so that I can create the moving effect exactly like sliding between pages of iOS application screen.
My class is like so:
class MyGameScreen: public cocos2d::CCLayer {
cocos2d::CCLayer* m_pNextScreen;
}
bool MyGameScreen::init() {
m_pNextScreen = MyOtherScreen::create();
}
void MyGameScreen::ccTouchesMoved(CCSet *touches, CCEvent *event){
// it crashes here... on the setPosition... m_pNextScreen is valid pointer though I am not sure that MyOtherScreen::create() is all I need to do...
m_pNextScreen->setPosition( CCPointMake( (fMoveTo - (2*fScreenHalfWidth)), 0.0f ) );
}
EDIT: adding clear question
It crashed when I try to setPosition on m_pNextScreen...
I have no idea why it crashed as m_pNextScreen is a valid pointer and is properly initialized. Could anybody explain why?
EDIT: adding progress report
I remodelled the whole system and make a class CContainerLayer : public cocos2d::CCLayer that contains both MyGameScreen and MyOtherScreen side by side. However, this looked like not an efficient approach, as when it grows I may need to have more than 2 pages scrollable side by side, I'd prefer to load the next page only when it is needed rather than the entire CContainerLayer that contains all the upcoming pages whether the user will scroll there or not... Do you have any better idea or github open source sample that does this?
Thank you very much for your input!
Use paging enable scrollview.download files from following link and place in your cocos2d/extenision/gui/ after that you have to set property of scrollview to enablepaging true with paging view size.
https://github.com/shauket/paging-scrollview
For Scene Transitions you can do this:
void MyGameScreen::ccTouchesMoved(CCSet *touches, CCEvent *event)
{
CCScene* MyOtherScene = CCTransitionFadeUp::create(0.2f, MyOtherScreen::scene());
CCDirector::sharedDirector()->replaceScene(MyOtherScene);
}

Categories

Resources