I am newer to xamarin forms and I am currently trying to add an outline to my text here. I am not quite sure how to go about it. I believe it may have something to do with a custom renderer. I have currently attempted to add a background color to the label text but id prefer it to stick more closely to the text.
Here is my main.xaml
<StackLayout>
<Grid Padding="40 "/>
<Label VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand" Text="Plural Buddy" TextColor="#000000" BackgroundColor="FloralWhite" FontFamily=" { StaticResource CustomFont3}" FontSize="Large" Padding="0" />
<Button VerticalOptions="StartAndExpand" HorizontalOptions="CenterAndExpand" Text="Get Started" BorderColor= "AntiqueWhite" FontFamily=" { StaticResource CustomFont3}" />
</StackLayout>
</ContentPage>
What effect do you want ? like below ?
If yes,you could use CustomRederen to achieve it.
For Android.
create custom label OutLineLabel :
public class OutLineLabel :Label
{
}
in Android project:
create a custom TextView StrokeTextView:
class StrokeTextView : TextView
{
private TextView borderText = null;
public StrokeTextView (Context context) : base(context)
{
borderText = new TextView(context);
init();
}
public StrokeTextView(Context context,IAttributeSet attrs) : base(context,attrs)
{
borderText = new TextView(context, attrs);
init();
}
public StrokeTextView(Context context, IAttributeSet attrs,int defStyle) : base(context, attrs,defStyle)
{
borderText = new TextView(context, attrs, defStyle);
init();
}
public void init()
{
TextPaint tp1 = borderText.Paint;
tp1.StrokeWidth =5; // sets the stroke width
tp1.SetStyle(Style.Stroke);
borderText.SetTextColor(Color.White); // set the stroke color
borderText.Gravity = Gravity;
}
public override ViewGroup.LayoutParams LayoutParameters { get => base.LayoutParameters; set => base.LayoutParameters = value; }
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
string tt = borderText.Text;
if (tt == null || !tt.Equals(this.Text))
{
borderText.Text = Text;
this.PostInvalidate();
}
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
borderText.Measure(widthMeasureSpec, heightMeasureSpec);
}
protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
{
base.OnLayout(changed, left, top, right, bottom);
borderText.Layout(left, top, right, bottom);
}
protected override void OnDraw(Canvas canvas)
{
borderText.Draw(canvas);
base.OnDraw(canvas);
}
}
create custom renderer MyOutLineTextView:
[assembly: ExportRenderer(typeof(OutLineLabel), typeof(MyOutLineTextView))]
namespace EntryCa.Droid
{
class MyOutLineTextView : LabelRenderer
{
Context context;
public MyOutLineTextView(Context context):base(context)
{
this.context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Control !=null)
{
StrokeTextView strokeTextView = new StrokeTextView(context);
strokeTextView.Text = e.NewElement.Text;
strokeTextView.SetTextColor(Android.Graphics.Color.Purple);
SetNativeControl(strokeTextView);
}
}
}
}
then in page.axml:
<StackLayout BackgroundColor="Black">
<local:OutLineLabel Text="Hellow World">
</local:OutLineLabel>
</StackLayout>
Related
I am using design support to create tabs. I am also using ViewPager for swipable tabs.
Now, I don't know how to use only icons instead of texts in tabs. I tried finding out but didn't get any success.
My code:
Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.pager);
setupViewPager(viewPager);
setupTablayout();
}
private void setupTablayout() {
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setupWithViewPager(viewPager);
}
class MyPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public MyPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
mFragmentTitleList.get(position)
}
}
private void setupViewPager(ViewPager viewPager) {
MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new frag(), "CAT");
adapter.addFrag(new frag(), "DOG");
adapter.addFrag(new frag(), "BIRD");
viewPager.setAdapter(adapter);
}
One approach is setting the icons after TabLayout.setupWithViewPager() method.
mTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
mTabLayout.getTabAt(i).setIcon(R.drawable.your_icon);
}
The tutorial shown in the following link should cover what you want. https://github.com/codepath/android_guides/wiki/Google-Play-Style-Tabs-using-TabLayout#add-icons-to-tablayout
I copied the relevant section below.
Add Icons to TabLayout
Currently, the TabLayout class does not provide a clean abstraction model that allows for icons in your tab. There are many posted workarounds, one of which is to return a SpannableString, containing your icon in an ImageSpan, from your PagerAdapter's getPageTitle(position) method as shown in the code snippet below:
private int[] imageResId = {
R.drawable.ic_one,
R.drawable.ic_two,
R.drawable.ic_three
};
// ...
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
// return tabTitles[position];
Drawable image = context.getResources().getDrawable(imageResId[position]);
image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
SpannableString sb = new SpannableString(" ");
ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
By default, the tab created by TabLayout sets the textAllCaps property to be true, which prevents ImageSpans from being rendered. You can override this behavior by changing the tabTextAppearance property.
<style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
<item name="tabTextAppearance">#style/MyCustomTextAppearance</item>
</style>
<style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
<item name="textAllCaps">false</item>
</style>
In new version of TabLayout, google added TabItem which easily can add Icon through your XML with following code:
<android.support.design.widget.TabLayout
app:tabTextColor="#color/gray"
app:tabMode="fixed"
app:tabBackground="#color/red"
app:tabIndicatorHeight="4dp"
app:tabIndicatorColor="#color/purple"
app:tabPadding="2dp"
app:tabSelectedTextColor="#color/white"
app:tabMinWidth="64dp"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<!--add height and width to TabItem -->
<android.support.design.widget.TabItem
android:text="#string/tab_text"/>
<android.support.design.widget.TabItem
android:icon="#drawable/ic_android"/>
</android.support.design.widget.TabLayout>
See more here.
try this
public class GlobalActivity extends AppCompatActivity {
Toolbar toolbar;
ViewPager viewPager;
TabLayout tabLayout;
ViewPagerAdapter adapter;
private int[] tabIcons = {
R.drawable.home_ic,
R.drawable.biz_ic,
R.drawable.network_ic,
R.drawable.offers_ic,
R.drawable.message_ic_b
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_global_hub);
tab();
}
public void tab(){
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
tabLayout.getTabAt(3).setIcon(tabIcons[3]);
tabLayout.getTabAt(4).setIcon(tabIcons[4]);
}
public void setupViewPager(ViewPager viewPager){
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new GlHubFragment(),"HOME");
adapter.addFrag(new BizForumFragment(), "BIZ FORUM");
adapter.addFrag(new NetworkFragment(), "NETWORK");
adapter.addFrag(new MessagesFragment(), "MESSAGEs");
adapter.addFrag(new OfferFragmentActivity(), "OFFER");
viewPager.setAdapter(adapter);
}
public class ViewPagerAdapter extends FragmentPagerAdapter{
private final List<Fragment> mfragmentlist =new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return mfragmentlist.get(position);
}
#Override
public int getCount() {
return mfragmentlist.size();
}
public void addFrag(Fragment fragment,String title){
mfragmentlist.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position){
return mFragmentTitleList.get(position);
}
}
}
In TabLayout, setting icon is easy:
getPageTitle(position) should return null (if you don't want title to show).
Next :
tabLayout.getTabAt(0).setIcon(resId);
tabLayout.getTabAt(1).setIcon(resId);
......
None of these methods are elegant when using TabLayout as the ViewPager "decor" scenario. TabLayout Documentation Here is a simple extension of TabLayout and PagerAdapter that provides a simple drop in replacement for TabLayout that should be able to be used in either scenario without manually adding icons outside of the TabLayout class and following the usage of PagerAdapter to get the tab information.
/**
* Created by JDL on 1/18/2017.
*/
public class TabLayoutExt extends TabLayout {
protected ViewPager mViewPager;
public abstract static class TabLayoutViewPagerAdapter extends PagerAdapter {
public TabLayoutViewPagerAdapter() {
}
/**
* This method may be called by the TabLayout to obtain an icon drawable
* to for the specified tab. This method may return null
* indicating no tab icon for this page. The default implementation returns
* null.
*
* #param position The position of the title requested
* #return A drawable icon for the requested page
*/
public Drawable getPageIcon(Context context, int position) {
return null;
}
}
public TabLayoutExt(Context context) {
super(context);
}
public TabLayoutExt(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TabLayoutExt(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onAttachedToWindow() {
//Cover the implicit setup in TabLayout
if (mViewPager == null) {
final ViewParent vp = getParent();
if (vp instanceof ViewPager) {
mViewPager = (ViewPager)vp;
}
}
super.onAttachedToWindow();
}
public void addTab(#NonNull Tab tab, int position, boolean setSelected) {
if (mViewPager != null && mViewPager.getAdapter() instanceof TabLayoutViewPagerAdapter) {
Drawable icon = ((TabLayoutViewPagerAdapter) mViewPager.getAdapter()).getPageIcon(getContext(),position);
tab.setIcon(icon);
}
super.addTab(tab,position,setSelected);
}
#Override
public void setupWithViewPager(#Nullable ViewPager viewPager, boolean autoRefresh) {
mViewPager = viewPager;
super.setupWithViewPager(viewPager, autoRefresh);
}
}
So all that needs be done is extend TabLayoutViewPagerAdapter instead of PageAdapter and implement getPageIcon(Context,int) instead of or in addition to title. The drop in TabLayoutExt in your XML file, instead of the normal TabLayout. This could be extended for further modifying the tab, either with a custom view instead or something else.
With the TabLayout provided by the Material Components Library you can use:
the method setIcon to define the resourceId
the method setTabLabelVisibility to set the TAB_LABEL_VISIBILITY_UNLABELED.
Something like:
for (int i=0;i<tabLayout.getTabCount();i++){
tabLayout.getTabAt(i).setIcon(iconResId);
tabLayout.getTabAt(i).
setTabLabelVisibility(TabLayout.TAB_LABEL_VISIBILITY_UNLABELED);
}
The easiest way I've found to use icons is to use Tablayout.Tab.setIcon(drawable). This also makes it easy to highlight the selected icon. If you want to do this, follow these steps.
Step 1.
Add your images to the res.mipmap folders. (mipmap-mdpi, hdpi etc.) Judging by the other answers here it's also fine to put then in the res.drawable folders.
Step 2.
Call setIcon on all your tabs after setting up your TabLayout and ViewPager. I did this in my AdapterTabs to keep the Activity tidy.
So in your activity do this:
tablayout = (TabLayout) findViewById(R.id.tab_layout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
adapterTabs = new AdapterTabs(this, getSupportFragmentManager(), fragments, tablayout, viewPager);
viewPager.setAdapter(adapterTabs);
tablayout.setupWithViewPager(viewPager);
adapterTabs.setTabIcons();
and in your AdapterTabs, which should extend FragmentPagerAdapter, put your setTabIcons() method.
public void setTabTitlesToIcons() {
Drawable icon1 = context.getResources().getDrawable(R.mipmap.ic_1);
Drawable icon2 = context.getResources().getDrawable(R.mipmap.ic_2);
Drawable icon3 = context.getResources().getDrawable(R.mipmap.ic_3);
Drawable icon1Hilighted = context.getResources().getDrawable(R.mipmap.ic_1_selected);
Drawable icon2Hilighted = context.getResources().getDrawable(R.mipmap.ic_2_selected);
Drawable icon3Hilighted = context.getResources().getDrawable(R.mipmap.ic_3_selected);
icons.add(icon1);
icons.add(icon2);
icons.add(icon3);
iconsHilighted.add(icon1Hilighted);
iconsHilighted.add(icon2Hilighted);
iconsHilighted.add(icon3Hilighted);
for(int i = 0; i < icons.size(); i++) {
if(i == 0) {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(iconsSelected.get(i));
}
else {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(icons.get(i));
}
}
}
Make sure to store a reference to the two lists 'icons' and 'iconsHilighted'. You'll need them later. Also store a reference to the TabLayout and the ViewPager which you passed in from the activity.
Step 3.
Make sure AdapterTabs.getPageTitle() returns null.
At this point, if you run it you should see that the first icon is highlighted.
Step 4.
Implement ViewPager.OnPageChangeListener in AdapterTabs and add that listener to your viewPager
public AdapterTabs(Context context, FragmentManager fragmentManager, List<Fragment> fragments, TabLayout tabLayout, ViewPager viewPager) {
super(fragmentManager);
this.context = context;
this.tabLayout = tabLayout;
this.viewPager = viewPager;
this.viewPager.addOnPageChangeListener(this);
tabs.add(fragments.get(0));
tabs.add(fragments.get(1));
tabs.add(fragments.get(2));
}
Step 5.
Update the icons in the tabs in the onPageSelected callback in your AdapterTabs.
#Override
public void onPageSelected(int position) {
for (int i = 0; i < tabs.size(); i++) {
if(i == position) {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(iconsSelected.get(i));
}
else {
//noinspection ConstantConditions
tabLayout.getTabAt(i).setIcon(icons.get(i));
}
}
}
Now you should see the hilighted icon being updated when you change tabs.
Try this this will definitely work .
private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
R.drawable.single,
R.drawable.multiple};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_picker);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Choose contact");
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
tab();
}
public void tab(){
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Login());
adapter.addFragment(new Register());
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
}
}
As mentioned in the comments, defining the icons in the TabLayout does not work when using a PagerAdapter. For those using Kotlin, one workaround is to create an extension function like this:
fun TabLayout.setupWithViewPagerAndKeepIcons(viewPager : ViewPager?) {
val icons = mutableListOf<Drawable?>()
repeat(tabCount) {
icons.add(getTabAt(it)?.icon)
}
setupWithViewPager(viewPager)
repeat(tabCount) {
getTabAt(it)?.setIcon(icons.get(it))
}
}
Then in the layout.xml add your icons to the TabLayout:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout">
<com.google.android.material.tabs.TabItem
android:icon="#drawable/your_icon"/>
</com.google.android.material.tabs.TabLayout>
Finally, use the extension function to setup the TabLayout with a ViewPager.
tab_layout.setupWithViewPagerAndKeepIcons(view_pager)
the simplest way is create new table by setting Icon on tablayout. below code will create two tab with icon only. use this code on onCreate() method
tablayout = (TabLayout) findViewById(R.id.order_tablayout);
tablayout.addTab( tablayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_shopping_cart_white_24dp)) );
tablayout.addTab( tablayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_like2_fille_white_24dp)) );
Using a ViewPager. This is how I have a tab with an icon only and no text.
TabLayout tabs...
TabLayout.Tab tab = tabs.getTabAt(0);
tab.setText("");
tab.setIcon(R.drawable.yourIcon);
This may not be the best answer for all cases, but what I found did not solve my problem yet.
After having a look at Androids implementation of tabLayout.setupWithViewPager(ViewPager pager) I came up with a solution using just listeners.
The layout structure:
| LinearLayout (vertical)
|-- TabLayout (width: match_parent)
|---- TabItem (without text, just icons)
|---- TabItem
|---- ...
|-- ViewPager
Code for the both listeners:
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
pager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
tabLayout.setScrollPosition(position, positionOffset, false);
}
#Override
public void onPageSelected(int position) {
TabLayout.Tab tab = tabLayout.getTabAt(position);
if (tab != null) {
tab.select();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
Have a look at the tabLayout.setScrollPosition call inside OnPageChangeListener.onPageScrolled for the more or less good moving of the indicator while scrolling.
This may not work if the TabLayout's width is not set to match_parent (or must be scrollable).
I want this type of design ::
Here Is My design
My mainactivity.xml only contain a frameLayout which is Replaced by Selected Fragment from bottombar menu item.
It's code is here:
b = BottomBar.attach(this,savedInstanceState);
b.setItemsFromMenu(R.xml.menu_main, new OnMenuTabClickListener() {
#Override
public void onMenuTabSelected(#IdRes int menuItemId) {
if(menuItemId == R.id.BottomBarItemOne){
PeopleFragment p = new PeopleFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,p).commit();
}
else if(menuItemId == R.id.BottomBarItemTwo){
LocationFragment l = new LocationFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,l).commit();
}
else if(menuItemId == R.id.BottomBarItemThree){
HistoryFragment h = new HistoryFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,h).commit();
}
else if(menuItemId == R.id.BottomBarItemFour){
LikesFragment li = new LikesFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.frame,li).commit();
}
}
Now I want to create a tabview in on one of the Fragment :
For that I implement toolbar,tablayout and viewpager in required fragment xml file.
I created a separate java file contain viewPagerAdapter class.
public class viewPagerAdapter extends FragmentPagerAdapter {
ArrayList<Fragment> fragments = new ArrayList<>(); // this line can cause crashes
ArrayList<String> tabTitles = new ArrayList<>();
public void addFragment(Fragment fragment,String tabTitle){
fragments.add(fragment); // this line can cause crashes
tabTitles.add(tabTitle);
}
public viewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles.get(position);
}
}
Now I want to add this code to implement tablayout ::
toolbar = (Toolbar) findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPagerAdapter = new viewPagerAdapter(getSupportFragmentManager());
viewPagerAdapter.addFragment(new HomeFragment(),"Home"); // this line can cause crashes
viewPagerAdapter.addFragment(new MessageFragment(),"Message"); // this line can cause crashes
viewPagerAdapter.addFragment(new ContectFragment(),"Contect"); // this line can cause crashes
viewPager.setAdapter(viewPagerAdapter);
tabLayout.setupWithViewPager(viewPager);
In Fragment's onCreate method Given below ::
public class HomeFragment extends Fragment {
public HomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TabLyout Code Here
return inflater.inflate(R.layout.fragment_home, container, false);
}
}
But Android Studio doesn't allow Tablayout Fragment code in Fragment.
What Can I do ?
How can I implement tablayout in one of the fragment?
Try the following approach :
Add this to your fragment layout as per your requirement.
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="50dp"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabIndicatorColor="#color/tab_indicator"
app:tabIndicatorHeight="2.5dp"
app:tabPaddingBottom="-1dp"
app:tabPaddingEnd="-1dp"
app:tabPaddingStart="-1dp"
app:tabPaddingTop="-1dp"
app:tabBackground="#color/white"/>
Create one model for your tabs which you want to show.
Now add the following code in your fragment:
this.navigationData = new ArrayList<>();
this.navigationData.add(new MainNavigationViewModel("TAB-1", R.drawable.TAB-1, R.drawable.TAB-1, true));
this.navigationData.add(new MainNavigationViewModel("TAB-2", R.drawable.TAB-2, R.drawable.TAB-2, false));
this.navigationData.add(new MainNavigationViewModel("TAB-3", R.drawable.TAB-3, R.drawable.TAB-23, false));
for (MainNavigationViewModel vm : this.navigationData) {
tabLayout.addTab(tabLayout.newTab().setCustomView(ViewHelper.buildTabWithText(getContext(), vm.getText(), vm.getIsSelected())));
}
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
adapter = new MainFragmentPagerAdapter(getChildFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
Now create FragmentPagerAdapter (New class) like this.
public class MainFragmentPagerAdapter extends FragmentPagerAdapter {
private interface FragmentFactory {
Fragment create();
}
private static final FragmentFactory[] fragments = new FragmentFactory[] {
() -> LiveFeedFragment.getInstance(),
() -> GroupsFragment.getInstance(),
() -> NewsFragment.getInstance()
};
public MainFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public Fragment getItem(int position) {
return fragments[position].create();
}
#Override
public int getCount() {
return fragments.length;
}
}
And access the fragment like this way.
After updating the device to iOS 10, QLPreviewController stopped to display correctly the documents. It shows the white screen.
I have extracted the sample scenario from the app.
It contains single page with two buttons that should load two different documents:
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:QuickLookIOS10Test"
x:Class="QuickLookIOS10Test.QuickLookIOS10TestPage">
<StackLayout Orientation="Vertical">
<Button Text="Load first doc" Clicked="OnLoadFirstClicked"/>
<Button Text="Load second doc" Clicked="OnLoadSecondClicked"/>
<Button Text="Navigate forward" Clicked="OnForwardClicked"/>
<local:QLDocumentView
x:Name="DocumentView"
BackgroundColor="Silver"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"/>
</StackLayout>
</ContentPage>
where:
public class QLDocumentView : View
{
public static readonly BindableProperty FilePathProperty =
BindableProperty.Create(nameof(FilePath), typeof(string), typeof(QLDocumentView), null);
public string FilePath
{
get { return (string)GetValue(FilePathProperty); }
set { SetValue(FilePathProperty, value); }
}
}
There is a custom renderer involved:
public class QLDocumentViewRenderer : ViewRenderer<QLDocumentView, UIView>
{
private QLPreviewController controller;
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
//This is a fix to prevent incorrect scaling after rotating from portrait to landscape.
//No idea why does this work :( Bug #101639
return new SizeRequest(Size.Zero, Size.Zero);
}
protected override void OnElementChanged(ElementChangedEventArgs<QLDocumentView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
controller = new QLPreviewController();
SetNativeControl(controller.View);
}
RefreshView();
}
protected override void OnElementPropertyChanged(object sender,
System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == QLDocumentView.FilePathProperty.PropertyName)
{
RefreshView();
}
}
private void RefreshView()
{
DisposeDataSource();
if (Element?.FilePath != null)
{
controller.DataSource = new DocumentQLPreviewControllerDataSource(Element.FilePath);
}
controller.ReloadData();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
DisposeDataSource();
DisposeController();
}
}
private void DisposeDataSource()
{
var dataSource = controller.DataSource;
controller.DataSource = null;
dataSource?.Dispose();
}
private void DisposeController()
{
controller?.Dispose();
controller = null;
}
private class DocumentQLPreviewControllerDataSource : QLPreviewControllerDataSource
{
private readonly string fileName;
public DocumentQLPreviewControllerDataSource(string fileName)
{
this.fileName = fileName;
}
public override nint PreviewItemCount(QLPreviewController controller)
{
return 1;
}
public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
{
NSUrl url = NSUrl.FromFilename(fileName);
return new QlItem(url);
}
private sealed class QlItem : QLPreviewItem
{
private readonly NSUrl itemUrl;
public QlItem(NSUrl uri)
{
itemUrl = uri;
}
public override string ItemTitle { get { return string.Empty; } }
public override NSUrl ItemUrl { get { return itemUrl; } }
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
this.itemUrl?.Dispose();
}
}
}
}
}
If the application setups the main page like below:
MainPage = new NavigationPage(new QuickLookIOS10TestPage());
it does work on iOS 9.3 but not on iOS 10. If I remove NavigationPage:
MainPage = new QuickLookIOS10TestPage();
it works on both iOS versions.
The code behind for button clicks just sets the FilePath property of the control.
Sample app demonstrating the problem
Xamarin Forms 2.3.2.127
Xamarin Studio 6.1.1 (build 15)
I've faced with the same problem. It looks like something was changed or even broken in QuickLook in iOS10, but the solution is quite simple:
public class PdfViewerControlRenderer : ViewRenderer<PdfViewerControl, UIView>
{
private readonly bool IsOniOS10;
private UIViewController _controller;
private QLPreviewController _qlPreviewController;
public PdfViewerControlRenderer()
{
IsOniOS10 = UIDevice.CurrentDevice.CheckSystemVersion(10, 0);
}
protected override void OnElementChanged(ElementChangedEventArgs<PdfViewerControl> e)
{
if (e.NewElement != null)
{
_controller = new UIViewController();
_qlPreviewController = new QLPreviewController();
//...
// Set QuickLook datasource here
//...
if (!IsOniOS10)
{
_controller.AddChildViewController(_qlPreviewController);
_controller.View.AddSubview(_qlPreviewController.View);
_qlPreviewController.DidMoveToParentViewController(_controller);
}
SetNativeControl(_controller.View);
}
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
_controller.View.Frame = Bounds;
_controller.View.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
_qlPreviewController.View.Frame = Bounds;
if (IsOniOS10)
{
_controller.View.AddSubview(_qlPreviewController.View);
_qlPreviewController.DidMoveToParentViewController(_controller);
}
}
}
Result:
I am having an issue with list views on in a couple of my Xamarin Forms applications. One form is within a tabbed page setup, the other is a normal content page (different apps)
I have a class like this
public class SomeClass
{
public string StringOne {get;set;}
public string StringTwo {get;set;}
public int IntOne {get;set;}
}
In my Content page, I set up an ObservableCollection and add some data in. I then tell the list that SomeClass is my ItemSource. This produces the ListView correctly on all of my devices.
The problem is that when I change one of the properties, nothing on the ListView changes (so if say I have 3 objects in the Observable and remove one, the list still says 3 - or if I change a property in my second object, the second item on the ListView doesn't change either).
I have also tried to solve the problem by using a standard List and implement INotifyChanged within the class. Again though, the ListView doesn't alter when the List changes.
I know the data has altered as if I make a change to the object, come out and go back in, the data has changed in the UI.
Am I doing something wrong or is this a bug I need to putting into Bugzilla?
It will not change if you don't bind it and implement INotifyPropertyChanged interface.
Sample Code:
public class ObservableProperty : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class SomeClass:ObservableProperty
{
string stringOne;
string stringTwo;
int intOne;
public string StringOne
{
get{return stringOne;}
set
{
stringOne = value;
OnPropertyChanged("StringOne");
}
}
public string StringTwo
{
get{ return stringTwo;}
set
{
stringTwo = value;
OnPropertyChanged("StringTwo");
}
}
public int IntOne
{
get{ return intOne;}
set
{
intOne = value;
OnPropertyChanged("IntOne");
}
}
}
public class MainVM:ObservableProperty
{
ObservableCollection<SomeClass> items;
public ObservableCollection<SomeClass> items
{
get{return items;}
set
{
items = value;
OnPropertyChanged("Items");
}
}
public MainVM()
{
Items = new ObservableCollection<SomeClass>();
Items.Add(new SomeClass(){StringOne = "123", StringTwo = "test", IntOne =12});
}
public void CallMeForChangingProperty()
{
SomeClass item = Items[0];
item.StringOne = "Test1";
}
}
public class MainView
{
public MainView()
{
this.BindingContext= new MainVM()
}
}
< ListView ItemsSource="{Binding Items}" RowHeight="120">
< ListView.ItemTemplate>
< DataTemplate>
< ViewCell>
< ViewCell.View>
< StackLayout>
< Label Text= "StringOne" />
< Label Text= "StringTwo" />
< Label Text= "IntOne" />
</ StackLayout>
</ ViewCell.View>
</ ViewCell>
</ DataTemplate>
</ ListView.ItemTemplate>
</ ListView>
Answer given by #eakgul works like a charm for me.
I'll attach here what I've implemented, maybe it could help someone.
You have to set INotifyPropertyChanged both, to the ObservableColection and to it's itens.
I have a BaseViewModel with INotifyPropertyChanged as follows:
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
protected void SetProperty<T>(ref T backingField, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals( backingField, value)) return;
backingField = value;
OnPropertyChanged(propertyName);
}
}
On my BluetoothPage.xaml, first I set bindincontext to my BluetoothPageViewModel.cs and set the ListView ItemsSource and it's binded labels:
<ContentPage.BindingContext>
<viewmodel:BluetoothPageViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout Padding="5,10">
<Button x:Name="Scan_Devices_Button"
Command="{Binding SearchNew_Button_Clicked}"/>
<ListView x:Name="DevicesList"
ItemsSource="{Binding BluetoothDevices}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
IsPullToRefreshEnabled="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text="{Binding device.Device.NativeDevice.Name}"/>
<Label Grid.Column="1"
Text="{Binding device.Device.NativeDevice.Address, StringFormat='ID: {0}'}"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0"
Text="{Binding device.Rssi, StringFormat='Power: {0:F2}dbm'}"/>
<Label Grid.Column="1"
Text="{Binding distance, StringFormat='Distance: {0:F2}m'}"/>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
Then, in my BluetoothPageViewModel.cs I extend it with the BaseViewModel and declare ItemsSource BluetoothDevices with INotifyPropertyChanged. At this moment, everytime I change an item on the ObservableCollection BluetoothDevices, the ListView will be updated. But, If I made a change on an item inside the ObservableCollection, nothing will happen!
So, you must set INotifyPropertyChanged to it's itens.
Following is my BluetoothPageViewModel, which uses a class BluetoothPageModel in the PageModel BluetoothPageModel.cs
The BluetoothPageViewModel:
public class BluetoothPageViewModel : BaseViewModel
{
public BluetoothPageViewModel()
{
SearchNew_Button_Clicked = new Command(NewDevices_Button_Clicked_Event);
Scan_Devices_Button_BgColor = "#D6D7D7";
Scan_Devices_Button_Text = "Scan nearby devices";
}
#region Declarations
public List<IDevice> iDeviceList = new List<IDevice>();
public ObservableCollection<BluetoothPageModel> _bluetoothDevices = new ObservableCollection<BluetoothPageModel>();
public BluetoothPageModel _selectedItem;
public ObservableCollection<BluetoothPageModel> BluetoothDevices
{
get { return _bluetoothDevices; }
set { SetProperty(ref _bluetoothDevices, value); }
}
public BluetoothPageModel SelectedItem
{
get { return _selectedItem; }
set { SetProperty(ref _selectedItem, value); }
}
public ICommand SearchNew_Button_Clicked { get; private set; }
#endregion
#region Functions
private void NewDevices_Button_Clicked_Event(object obj)
{
// discover some devices
if (!CrossBleAdapter.Current.IsScanning)
{
BluetoothDevices.Clear();
iDeviceList.Clear();
var scanner = CrossBleAdapter.Current.Scan().Subscribe(scanResult =>
{
if (!iDeviceList.Contains(scanResult.Device))
{
iDeviceList.Add(scanResult.Device);
Device.BeginInvokeOnMainThread(() =>
{
BluetoothDevices.Add(new BluetoothPageModel
{
device = scanResult,
distance = Math.Pow(10, ((-68 - scanResult.Rssi) / 31.1474))
});
});
}
else
{
int ind = iDeviceList.IndexOf(scanResult.Device);
Device.BeginInvokeOnMainThread(() =>
{
BluetoothDevices[ind].device = scanResult;
BluetoothDevices[ind].distance = Math.Pow(10, ((-68 - scanResult.Rssi) / 31.1474));
});
}
});
}
else
{
CrossBleAdapter.Current.StopScan(); //When you want to stop scanning
}
}
#endregion
}
Finally, to be able to update data when you change a property of the BluetoothPageModel class:
public class BluetoothPageModel:BaseViewModel
{
public IScanResult _device;
public double _distance;
public IScanResult device
{
get { return _device; }
set { SetProperty(ref _device, value); }
}
public double distance
{
get { return _distance; }
set { SetProperty(ref _distance, value); }
}
}
Thanks to eakgul answer I could get it working. Hope it can help someone else.
I have an openCV application program working, but need to add buttons etc. to the layout. So basically I want to display the opencv camera view on a surfaceView and the add the other stuff underneath.
I've been searching the internet and forums for a while, only seeing the guy with a opencv facial detection application also wanting to add a custom layout... no solution.
I am really desperate for a solution so would hugely appreciate help. For this purpose I used the OpenCV sample 3 application (as a simple example) and tried to bind to a surfaceview on a simple custom layout. I managed it in a normal Camera application, but struggling quite a bit with the opencv example.
So this is the code that I have for the Sample3Native.java, Sample3View.java and SampleViewBase.java (as in example) files respectively:
public class Sample3Native extends Activity {
private Sample3View mView;
private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
// Load native library after(!) OpenCV initialization
System.loadLibrary("native_sample");
// Create and set View
mView = new Sample3View(mAppContext);
setContentView(R.layout.main);
//setContentView(mView);
// Check native OpenCV camera
mView.openCamera();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
//constructor
public Sample3Native() {}
#Override
protected void onPause() {
super.onPause();
if (null != mView)
mView.releaseCamera();
}
#Override
protected void onResume() {
super.onResume();
if((null != mView) && !mView.openCamera() ) {
AlertDialog ad = new AlertDialog.Builder(this).create();
ad.setCancelable(false); // This blocks the 'BACK' button
ad.setMessage("Fatal error: can't open camera!");
ad.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
});
ad.show();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack);
}
}
class Sample3View extends SampleViewBase {
private int mFrameSize;
private Bitmap mBitmap;
private int[] mRGBA;
public Sample3View(Context context) {
super(context);
}
#Override
protected void onPreviewStarted(int previewWidtd, int previewHeight) {
mFrameSize = previewWidtd * previewHeight;
mRGBA = new int[mFrameSize];
mBitmap = Bitmap.createBitmap(previewWidtd, previewHeight, Bitmap.Config.ARGB_8888);
}
#Override
protected void onPreviewStopped() {
if(mBitmap != null) {
mBitmap.recycle();
mBitmap = null;
}
mRGBA = null;
}
#Override
protected Bitmap processFrame(byte[] data) {
int[] rgba = mRGBA;
FindFeatures(getFrameWidth(), getFrameHeight(), data, rgba);
Bitmap bmp = mBitmap;
bmp.setPixels(rgba, 0, getFrameWidth(), 0, 0, getFrameWidth(), getFrameHeight());
return bmp;
}
public native void FindFeatures(int width, int height, byte yuv[], int[] rgba);
}
public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private Camera mCamera;
private SurfaceHolder mHolder;
private SurfaceView mViewer;
private int mFrameWidth;
private int mFrameHeight;
private byte[] mFrame;
private boolean mThreadRun;
private byte[] mBuffer;
public SampleViewBase(Context context) {
super(context);
mViewer = (SurfaceView)this.findViewById(R.id.camera_view);
mHolder = mViewer.getHolder();
mHolder.addCallback(this);
}
public int getFrameWidth() {
return mFrameWidth;
}
public int getFrameHeight() {
return mFrameHeight;
}
public boolean openCamera() {
releaseCamera();
mCamera = Camera.open();
if(mCamera == null)
return false;
mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
synchronized (SampleViewBase.this) {
System.arraycopy(data, 0, mFrame, 0, data.length);
SampleViewBase.this.notify();
}
camera.addCallbackBuffer(mBuffer);
}
});
return true;
}
public void releaseCamera() {
mThreadRun = false;
synchronized (this) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
onPreviewStopped();
}
public void setupCamera(SurfaceHolder holder,int width, int height) {
synchronized (this) {
if (mCamera != null) {
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
mFrameWidth = width;
mFrameHeight = height;
// selecting optimal camera preview size
{
int minDiff = Integer.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - height) < minDiff) {
mFrameWidth = size.width;
mFrameHeight = size.height;
minDiff = Math.abs(size.height - height);
}
}
}
params.setPreviewSize(getFrameWidth(), getFrameHeight());
List<String> FocusModes = params.getSupportedFocusModes();
if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
{
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
}
mCamera.setParameters(params);
/* Now allocate the buffer */
params = mCamera.getParameters();
int size = params.getPreviewSize().width * params.getPreviewSize().height;
size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
mBuffer = new byte[size];
/* The buffer where the current frame will be copied */
mFrame = new byte [size];
mCamera.addCallbackBuffer(mBuffer);
try {
mCamera.setPreviewDisplay(holder);
//mCamera.setPreviewDisplay(null);
} catch (IOException e) {}
/* Notify that the preview is about to be started and deliver preview size */
onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height);
/* Now we can start a preview */
mCamera.startPreview();
}
}
}
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
setupCamera(_holder,width, height);
}
public void surfaceCreated(SurfaceHolder holder) {
(new Thread(this)).start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
//abstract functions used by child class
protected abstract Bitmap processFrame(byte[] data);
protected abstract void onPreviewStarted(int previewWidtd, int previewHeight);
protected abstract void onPreviewStopped();
//================================
public void run() {
mThreadRun = true;
while (mThreadRun) {
Bitmap bmp = null;
synchronized (this) {
try {
this.wait();
bmp = processFrame(mFrame);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (bmp != null) {
Canvas canvas = mHolder.lockCanvas();
if (canvas != null) {
canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth()) / 2, (canvas.getHeight() - getFrameHeight()) / 2, null);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
I know this must be a MAJOR drag to go through my code, but I really need the help. Or even if I could get a link to a working example of this type of implementation. Also, please just don't send me this link (it doesn't help me):openCV in custom applications
This is my acitivity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:opencv="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<org.opencv.android.JavaCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="#+id/tutorial1_activity_java_surface_view"
opencv:show_fps="true"
opencv:camera_id="any" />
<org.opencv.android.NativeCameraView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"
android:id="#+id/tutorial1_activity_native_surface_view"
opencv:show_fps="true"
opencv:camera_id="any" />
<Button
android:id="#+id/btnOK"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="105dp"
android:layout_marginTop="139dp"
android:onClick="OKClicked"
android:text="#string/OK" />
<TextView
android:id="#+id/txtDisp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/btnOK"
android:layout_alignBottom="#+id/btnOK"
android:layout_marginLeft="25dp"
android:layout_toRightOf="#+id/btnOK"
android:text="#string/app_name"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
And these code must be edited to MainActivity.java class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (mIsJavaCamera){
mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.tutorial1_activity_java_surface_view);
}else{
mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.tutorial1_activity_native_surface_view);
}
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
ArrayList<View> views = new ArrayList<View>();
views.add(findViewById(R.id.btnOK));
views.add(findViewById(R.id.txtDisp));
mOpenCvCameraView.addTouchables(views);
}
public void OKClicked(View view){
TextView disp = (TextView)findViewById(R.id.txtDisp);
disp.setText("OK Clicked");
}
This code is modified to OpenCV Tutorial 1.
You will see a button and a TextView over the surfaceview. When you click OK button TextView will show "OK Clicked". This is working for me on Samsung Galaxy.