I have RecyclerView which contains user bookmarks. The plan is bookmarked item will be marked with certain icon. This is my code in onBindViewHolder():
// ...
if (bookmarks != null) {
for (BookmarkModel bookmarkData : bookmarks) {
if (bookmarkData.getLetterId() == letter && bookmarkData.getEntryId() == entry) {
holder.imgBookmark.setVisibility(View.VISIBLE);
} else {
holder.imgBookmark.setVisibility(View.INVISIBLE);
}
}
}
However, the RecyclerView is not showing all bookmark icons, only a few of them. Currently I have 3 bookmarks yet it only shows 1 of them. I have debug it and verified that holder.imgBookmark.setVisibility(View.VISIBLE) have been called 3 times. How to update the image properly?
I forgot to put break when the letter and entry match. Because of it, only the last match would show the icon.
if (bookmarks != null) {
for (BookmarkModel bookmarkData : bookmarks) {
if (bookmarkData.getLetterId() == letter && bookmarkData.getEntryId() == entry) {
holder.imgBookmark.setVisibility(View.VISIBLE);
break;
} else {
holder.imgBookmark.setVisibility(View.INVISIBLE);
}
}
}
Related
I have a project that use Android to display Unity Player. So I export Untiy project as Android module which implemented by Android Application.
I create buttons in Android Activity which contains UnityPlayer, And when I click button, it send a message to Unity Player to invoke C# function, just like this:
findViewById(R.id.btnChange).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mUnityPlayer.UnitySendMessage("ScriptHolder", "ChangeSkin", "");
}
});
And the function named "ChangeSkin" is just to change some GameObjects' active. Just like this:
void ChangeSkin()
{
int prefab;
if (_currentPrefab == PREFAB_DEFAULT)
{
prefab = PREFAB_PRINCESS;
}
else
{
prefab = PREFAB_DEFAULT;
}
ShowSkin(prefab);
}
private void ShowSkin(int prefab)
{
_currentPrefab = prefab;
foreach (var item in _defaultDressList)
{
item.SetActive(prefab == PREFAB_DEFAULT);
}
foreach (var item in _princessDressList)
{
item.SetActive(prefab == PREFAB_PRINCESS);
}
}
And something weird happening: when I click button to change the person's cloth in Unity, the GameObjects which called SetActive(true) show at the position above the right position for a frame and become normal, it looks like they flash. Here is the gif of the project demo:
It looks like the position offset is equal to the height of status bar. If I create a button on Unity Scene and call "ChangeSkin" function, everything will be OK.
I tried all I can to fix this but not succeed. So I hope you will help me, thx.
You should check your Unity layout. If you have a layout group that has content size fitter component, and the child objects also have it (content size fitter), this could cause these glitches.
I fixed this problem by using a flag (or trigger). Just like this:
// set value true to trigger ChangeSkin() in Update(),
// instead of invoke ChangeSkin() directly
private bool _changingSkinTrigger = false;
void ChangeSkin()
{
if (_currentPrefab == PREFAB_DEFAULT)
{
_currentPrefab = PREFAB_PRINCESS;
}
else
{
_currentPrefab = PREFAB_DEFAULT;
}
_changingSkinTrigger = true;
}
void Update()
{
if (_changingSkinTrigger)
{
_changingSkinTrigger = false;
ShowSkin();
}
}
private void ShowSkin()
{
foreach (var item in _defaultDressList)
{
item.SetActive(_currentPrefab == PREFAB_DEFAULT);
}
foreach (var item in _princessDressList)
{
item.SetActive(_currentPrefab == PREFAB_PRINCESS);
}
}
Thank #AndriyMarshalek for enlightening me.
I have an AR Screen where I placed some 3d objects. I am using google AR Core with android SDK.
I need to remove those objects from the scene on clicking of a clear button.
I was able to remove the last placed object. But the other objects were not removing.
This is the code i am using.
if (newAnchor != null) {
arFragment.getArSceneView().getScene().removeChild(newAnchor);
newAnchor.getAnchor().detach();
you can detach android model from scene form using below code
List<Node> children = new ArrayList<>(arFragment.getArSceneView().getScene().getChildren());
for (Node node : children) {
if (node instanceof AnchorNode) {
if (((AnchorNode) node).getAnchor() != null) {
((AnchorNode) node).getAnchor().detach();
}
}
if (!(node instanceof Camera) && !(node instanceof Sun)) {
node.setParent(null);
}
}
You can detect if a user has tapped on a particular node like this - in this example the check is to see if the hit node is an 'Andy' renderable, i.e. the default example renderable with Sceneform:
private void handleOnTouch(HitTestResult hitTestResult, MotionEvent motionEvent) {
Log.d(TAG,"handleOnTouch");
// First call ArFragment's listener to handle TransformableNodes.
arFragment.onPeekTouch(hitTestResult, motionEvent);
// Check for touching a Sceneform node
if (hitTestResult.getNode() != null) {
Log.d(TAG,"handleOnTouch hitTestResult.getNode() != null");
Node hitNode = hitTestResult.getNode();
if (hitNode.getRenderable() == andyRenderable) {
//DO whatever you need to here...
}
return;
And you can delete a node like this:
private void removeAnchorNode(AnchorNode nodeToremove) {
//Remove an anchor node
if (nodeToremove != null) {
arFragment.getArSceneView().getScene().removeChild(nodeToremove);
anchorNodeList.remove(nodeToremove);
nodeToremove.getAnchor().detach();
nodeToremove.setParent(null);
nodeToremove = null;
} else {
//Handle error case here
}
}
Full code available here: https://github.com/mickod/LineView - the above are edited excerpts.
If you need to cleanup the scene, you can do the following:
arSceneView.getScene().callOnHierarchy(node -> {
node.setParent(null);
if (node instanceof AnchorNode) {
((AnchorNode) node).getAnchor().detach();
}
}
While I'm reading the android.R.attr documentation, I found the breadCrumbTitle and breadCrumbShortTitle. What is the usage of these 2 attributes? Does android provide a breadCrumb view in platform base and if so what is it looks like? Why did these 2 attribute exist?
They're used in the PreferenceActivity:
sa.peekValue(com.android.internal.R.styleable.PreferenceHeader_breadCrumbTitle);
Specifically, they're set on PreferenceActivity.Header instances that are being pulled out of a preference_headers XML file:
tv = sa.peekValue(com.android.internal.R.styleable.PreferenceHeader_breadCrumbTitle);
if (tv != null && tv.type == TypedValue.TYPE_STRING) {
if (tv.resourceId != 0) {
header.breadCrumbTitleRes = tv.resourceId;
} else {
header.breadCrumbTitle = tv.string;
}
}
Unfortunately, there's very little documentation about what this feature does - where it shows up, how it's used on different API levels, etc. The official Settings guide doesn't even mention them.
There's also a concept of FragmentBreadCrumbs but that doesn't appear to use this attribute (and is even more sparsely documented!).
Edit: Looking further, it turns out that these features work in tandem! If the preference headers have breadcrumbs set, then those breadcrumbs are used in conjunction with the FragmentBreadCrumbs widget, assuming one exists with the id android.R.id.title, and we're in a multi-pane preferences page:
/**
* Change the base title of the bread crumbs for the current preferences.
* This will normally be called for you. See
* {#link android.app.FragmentBreadCrumbs} for more information.
*/
public void showBreadCrumbs(CharSequence title, CharSequence shortTitle) {
if (mFragmentBreadCrumbs == null) {
View crumbs = findViewById(android.R.id.title);
// For screens with a different kind of title, don't create breadcrumbs.
try {
mFragmentBreadCrumbs = (FragmentBreadCrumbs)crumbs;
} catch (ClassCastException e) {
setTitle(title);
return;
}
if (mFragmentBreadCrumbs == null) {
if (title != null) {
setTitle(title);
}
return;
}
if (mSinglePane) {
mFragmentBreadCrumbs.setVisibility(View.GONE);
// Hide the breadcrumb section completely for single-pane
View bcSection = findViewById(com.android.internal.R.id.breadcrumb_section);
if (bcSection != null) bcSection.setVisibility(View.GONE);
setTitle(title);
}
mFragmentBreadCrumbs.setMaxVisible(2);
mFragmentBreadCrumbs.setActivity(this);
}
if (mFragmentBreadCrumbs.getVisibility() != View.VISIBLE) {
setTitle(title);
} else {
mFragmentBreadCrumbs.setTitle(title, shortTitle);
mFragmentBreadCrumbs.setParentTitle(null, null, null);
}
}
So I'm trying to do the following in android xamarin.
When you press on a map element an infowindow is shown.When you press that window and an event is linked to the element the app goes to another fragment that is described by the action object. The problem is the moment I press the infowindow the whole app freezes and nothing happens. In the logs I can't see anything and the app stops at the following line:
pager.Adapter = pagerAdapter;
Added a breakpoint there and after saying "step over" the ide doesn't break anymore and the app freezes (no user interaction possible).
So let me start by giving all the relative code and a little explanation.
So first I'll show you what happens on the infowindow click. This happens on a SupportMapFragment that has it's own listener.
void GoogleMap.IOnInfoWindowClickListener.OnInfoWindowClick (Marker p0)
{
InfoPopup ip = CustomJsonConverter.Convert<InfoPopup> (p0.Title);
if (ip == null || ip.Goto == null || !(this.Activity is MainView))
return;
MainView main = (this.Activity as MainView);
p0.HideInfoWindow ();
switch (ip.Goto.type) {
case "InfoFragment":
Info info = InfoController.Items.Find (x => x.Index == ip.Goto.id);
if (info != null) {
main.RunOnUiThread (() => {
main.ShowInfosFragment ();
main.ShowInfoFragment (info);
});
}
break;
case "FaqFragment":
FaQ faq = FaQController.Items.Find (x => x.Index == ip.Goto.id);
if (faq != null) {
main.RunOnUiThread (() => {
main.ShowFaqsFragment ();
main.ShowFaqFragment (faq);
});
}
break;
}
}
I tested it with an action of InfoFragment which gives back an item so that's good. Then it goes to the main.ShowInfosFragment() which is where it freezes. So that method is really simple. This function is in the Activity holding the fragments (thanks Cheesebaron).
public void ShowInfosFragment(){
ShowFragment(1, new InfosFragment (){ InfoSelectedAction = ShowInfoFragment });
}
So the problem giving function is the following. This function is in the Activity holding the fragments (thanks Cheesebaron).
protected void ShowFragment(int index, Android.Support.V4.App.Fragment fragment, bool ignoreType = false){
RemoveSubMenu();
if (pagerAdapter.Count <= index || ignoreType || !(pagerAdapter.GetItem (index).GetType().Equals(fragment.GetType()))) {
pagerAdapter.AddFragment (index, fragment);
SetSubMenu (fragment);
pager.Adapter = pagerAdapter;
}
pager.SetCurrentItem (index, true);
DrawerButtonLayout ();
}
I've used this function a lot and it has always worked to move to the other fragments from the menu or at startup to set the mapfragment.
Anyone sees what's the problem with my code? Tried tons of things but can't seem to figure this one out with my friend google.
Thanks already for reading.
Kind regards,
Karl
So What I would like to do here is that the starting image is assigned with Tag 0. When I run the method, I want the image to change to gallows1 and get a tag of "1". Then when its run again, I want it to keep gallows1 with a tag of 1, and then change it to gallows2, and reassign it.... Basically, I want 1 image to change to the next, and so forth as the method runs 6 times.
Here is what I have so far.
public void switchImage(View view) {
ImageView img = (ImageView) findViewById(R.id.imageView1);
img.setTag("0");
if (img.getTag() == "0") {
img.setImageResource(R.drawable.gallows1);
img.setTag("1");
} else if (img.getTag() == "1") {
img.setImageResource(R.drawable.gallows2);
img.setTag("2");
} else if (img.getTag() == "2") {
img.setImageResource(R.drawable.gallows3);
img.setTag("3");
} else if (img.getTag() == "3") {
img.setImageResource(R.drawable.gallows4);
img.setTag("4");
} else if (img.getTag() == "4") {
img.setImageResource(R.drawable.gallows5);
img.setTag("5");;
} else if (img.getTag() == "5") {
img.setImageResource(R.drawable.gallows6);
img.setTag("6");
} else if (img.getTag() == "6") {
return;
}
}
The Game I am making is hangman, but instead of using graphics, I wanted to have a twist (its for a challenge proj) and have progressing images show up instead.
Put this outside the method:
ImageView img = (ImageView) findViewById(R.id.imageView1);
img.setTag("0")
and remove img.setTag("0") from inside the method
The way you have it now, img.setTag("0") gets called everytime so it will always just hit the first if block. If you move it outside, then the first time the method is called, if block 1 will match, then the next time, if block 2, etc.