Xamarin Android: Resource.designer Id does not match Android component Id - xamarin

I am trying to find an ImageView within the SearchView widget, the ImageView's Id name is search_close_btn. I'm looking it up with this line of code however it returns null.
closeButton = searchView.FindViewById(Resource.Id.search_close_btn);
I investigated the children of the search view and found the ImageView and discovered that the Id of the child did not match the one from the designer.
I'm curious to where the correct Id is stored as I have to search the view manually in order to find it.
Is java's R.Id the equivalent to Xamarin's Resource.Id

Try the following once you have a reference to your SearchView:
int searchPlateId = searchView.Context.Resources.GetIdentifier("android:id/search_plate", null, null);
View searchPlate = searchView.FindViewById(searchPlateId);
if (searchPlate != null)
{
int imgViewId = searchPlate.Context.Resources.GetIdentifier("android:id/search_close_btn", null, null);
ImageView imgView = (ImageView)searchPlate.FindViewById(imgViewId);
if (imgView != null)
{
Console.WriteLine("Found you image view: {0}", imgView);
}
}

Related

Xamarin iOS ToolbarItem Image showing white image

Xamarin Forms IconImageSource:
On Android Toolbar image is shown correctly, on iOS a white image is shown. How can I fix this?
I added file to Resources folder and set build Action to BundleResource.
If I change filename to non excisting file, image is not shown at all. I tried changing extension to JPG, same result, also a white image is shown.
I used this code snippit.
ToolbarItem toolbarItemSearch = new ToolbarItem { IconImageSource = ImageSource.FromFile("searchIcon.png") };
ToolbarItems.Add(toolbarItemSearch);
iOS has tinting the ToolbarItems by default , the color is blue/white .
To solve it we need to create a custom renderer for NavigationPage , and set the TintColor to transparent , and set the image with another rendering mode .
Sample code
[assembly: ExportRenderer(typeof(NavigationPage), typeof(MyRenderer))]
namespace FormsApp.iOS
{
class MyRenderer : NavigationRenderer
{
public override void PushViewController(UIViewController viewController, bool animated)
{
base.PushViewController(viewController, animated);
var currentPage = (this.Element as Xamarin.Forms.NavigationPage)?.CurrentPage;
if (this.NavigationBar == null || currentPage == null)
return;
var buttonItems = TopViewController.NavigationItem.RightBarButtonItems;
foreach (var button in buttonItems)
{
if(button.Image != null){
button.Image = button.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
button.TintColor = UIColor.Clear;
}
}
}
}
}
Refer to
Image in Toolbar item on iOS are white(Xamarin Forms)
The solution from #ColeX - MSFT did the trick! Additionally make sure to do a null pointer check for non Image buttons.

How to get IEditorOperations from IVsTextView?

I'm developing my first Visual Studio (2015 Community) Command Menu and I'm trying to get access to IEditorOperations to delete text, send backspace etc. but I'm not sure how to. I can do:
var Service = Provider.GetService(typeof(IEditorOperationsFactoryService)) as IEditorOperationsFactoryService;
Service.GetEditorOperations(???);
I'm not sure what to pass in the ??? since I don't have access to an ITextView instead what I have is a IVsTExtView via:
IVsTextView View;
IVsTextManager Manager = (IVsTextManager)ServiceProvider.GetService(typeof(SVsTextManager));
int MustHaveFocus = 1;
Manager.GetActiveView(MustHaveFocus, null, out View);
When creating the Command Menu, VS generates a template for me with a private ctor creating the command service, binding it to the command set id etc. An overridden Initialize method, and a bunch of properties.
Any ideas?
EDIT: After help from Sergey, I managed to get a bit further. But now I get a null when I try to get the IEditorOperationsFactoryService, all the other values are valid.
static IEditorOperations GetEditorService(IServiceProvider Provider, IVsTextView VsView)
{
IEditorOperations Result;
try
{
var Model = (IComponentModel)Provider.GetService(typeof(SComponentModel));
var Editor = (IEditorOperationsFactoryService)Provider.GetService(typeof(IEditorOperationsFactoryService)); // returns null
var Adaptor = Model.GetService<IVsEditorAdaptersFactoryService>();
IWpfTextView TextView = Adaptor.GetWpfTextView(VsView);
Result = Editor.GetEditorOperations(TextView);
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.ToString());
Result = null;
}
return (Result);
}
You can get IEditorOperationsFactoryService instance from variable named Model, like this:
var Model = (IComponentModel)this.ServiceProvider.GetService(typeof(SComponentModel));
var Editor = (IEditorOperationsFactoryService)Model.GetService<IEditorOperationsFactoryService>();
You can get IWpfTextView (that implements ITextView) from IVsTextView using:
IVsTextView textView = ...;
IWpfTextView v = GetEditorAdaptersFactoryService().GetWpfTextView(textView);
private Microsoft.VisualStudio.Editor.IVsEditorAdaptersFactoryService GetEditorAdaptersFactoryService()
{
Microsoft.VisualStudio.ComponentModelHost.IComponentModel componentModel =
(Microsoft.VisualStudio.ComponentModelHost.IComponentModel)serviceProvider.GetService(
typeof(Microsoft.VisualStudio.ComponentModelHost.SComponentModel));
return componentModel.GetService<Microsoft.VisualStudio.Editor.IVsEditorAdaptersFactoryService>();
}

Ripple Effect gone after adding TapGestureRecognizer to ViewCell

I added a custom LongPressGestureRecognizer to the ViewCell's root layout to handle certain cases, but after adding it, I find that the ripple effect when tapping the ViewCell is gone on Android. I tried to add back the animation by getting the native view, set background drawable to Android.Resource.Attribute.SelectableItemBackground by using below code
int[] attrs = { Android.Resource.Attribute.SelectableItemBackground };
var ta = CrossCurrentActivity.Current.Activity.ObtainStyledAttributes(attrs);
var drawable = ta.GetDrawable(0);
nativeView.SetBackgroundDrawable(drawable);
ta.Recycle();
Even this doesn't work. Any other way to make it work?
For those who want to know, I discarded the custom long press gesture recognizer way of achieving the goal, since it's the wrong way of doing things. On Android, we should use ItemLongClick event instead. Here is what I did, first, find out the native ListView through some method, my way is to first get the renderer of the ListView, then get underlying ListView. Another way is to use below code to find the ListView, but this way requires more work if you have multiple ListView
public static List<T> FindViews<T>(this ViewGroup viewGroup) where T : View
{
var result = new List<T>();
var count = viewGroup.ChildCount;
for (int i = 0; i < count; i++)
{
var child = viewGroup.GetChildAt(i);
var item = child as T;
if (item != null)
{
result.Add(item);
}
else if (child is ViewGroup)
{
var innerResult = FindViews<T>(child as ViewGroup);
if (innerResult != null)
{
result.AddRange(innerResult);
}
}
}
return result;
}
var rootView =(ViewGroup)CurrentActivity.Window.DecorView.RootView
var nativeListView = rootView.FindView<Android.Widget.ListView>();
Then override the OnAppearing method of the Page, in it, attach ItemLongClick event handler. Also override OnDisappearing method, in it, detach the ItemLongClick event handler. This is important. Simply add ItemLongClick event handler in constructor seems not working.

Get currently selected text in active application in Cocoa

I have a status-menu app that can be started using a system wide shortcut. When the app gets active, it would be great if I could somehow get the text that is selected in the currently running application.
So for example I type something in my text-editor, select the text, hit my global shortcut, my app comes up and I would now love to know the selected text from the text-editor.
What I have so far is the following (adopted code from How to get global screen coordinates of currently selected text via Accessibility APIs.)
AXUIElementRef systemWideElement = AXUIElementCreateSystemWide();
AXUIElementRef focussedElement = NULL;
AXError error = AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedUIElementAttribute, (CFTypeRef *)&focussedElement);
if (error != kAXErrorSuccess) {
NSLog(#"Could not get focussed element");
} else {
AXValueRef selectedTextValue = NULL;
AXError getSelectedTextError = AXUIElementCopyAttributeValue(focussedElement, kAXSelectedTextAttribute, (CFTypeRef *)&selectedTextValue);
if (getSelectedTextError == kAXErrorSuccess) {
selectedText = (__bridge NSString *)(selectedTextValue);
NSLog(#"%#", selectedText);
} else {
NSLog(#"Could not get selected text");
}
}
if (focussedElement != NULL) CFRelease(focussedElement);
CFRelease(systemWideElement);
The problem here is that it does not work with apps like Safari and Mail...
Thanks
This is actually very easy, kAXSelectedTextAttribute is your friend.
extension AXUIElement {
var selectedText: String? {
rawValue(for: kAXSelectedTextAttribute) as? String
}
func rawValue(for attribute: String) -> AnyObject? {
var rawValue: AnyObject?
let error = AXUIElementCopyAttributeValue(self, attribute as CFString, &rawValue)
return error == .success ? rawValue : nil
}
}
This is not technically a solution to your exact question because the user would have to trigger this from the Services menu rather than it simply happening when they trigger your menu bar app.
You could use a System Service. You create a service for your app that sends the currently selected text to your menu bar app via a Pasteboard.

listview asyncimage mismatch

i used the Android-Universal-Image-Loader(https://github.com/nostra13/Android-Universal-Image-Loader) for my project,but i get a strange problem:
the image loaded from the website was dismatch with the listview item when i scroll fast or fling fast...
i mean the listview item will load the wrong image sometimes,here is the code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Map<String, Object> item = mDatasource.get(position);
View view = convertView;
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
view = mInflater.inflate(R.layout.block_list_item, null);
holder.account_name = (TextView) view.findViewById(R.id.author_name);
holder.account_avatar = (ImageView) view.findViewById(R.id.view_header);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.account_name.setText(StringUtils.convertSafeString(item.get("account_name")));
String avatarUrl = UrlHelper.HOST + item.get("account_avatar");
if (!avatarUrl.endsWith(Constants.NO_AVATAR)) {
holder.account_avatar.setTag(avatarUrl);
imageLoader.displayImage(avatarUrl,holder.account_avatar, mOptions);
}
return view;
}
Well, I don't know this is going to help or not
I had a similar problem but I was using Parse, meaning I am getting my images from parse server
I managed to solve the problem when I discovered that the method I am using to get the image was meant to open a new thread rather than the UI thread and get the image in background (getParseFile().getDataInBackGround), when I changed it to another method which doesn't use another thread(getParseFile().getData()), it worked without problems.

Resources