How to create a customizable and reusable component? - android

I designed an action bar that has several variations:
As you can see this action bar always has a header and there may be action buttons.
I understand that I can just create five action bars and use them. But I want to create one component and reuse it everywhere in my application.
For example, in ReactJS I would just create one component ActionBar with some properties and reuse it where I need it, such as:
<ActionBar
isBackButton = true
text = "Screen name"
actionButton = "Add"
/>
or
<ActionBar
isBackButton = false
text = "Another screen name"
actionButton = "None"
/>
How do I achieve this?
Or should I not get steamed up and just create five different action bars?
Or create a universal action bar with text, right and left buttons, and then dynamically customize button icons, text and onClick actions in java code?
I definitely need your advice on what to do.

So the easiest way to do this is with a custom view. You'd create a layout file for it:
toolbar.xml (this is simplifies to just give the basic idea, you need to fill in all the styling data:
<LinearLayout>
<ImageView android:id="#+id/back"/>
<TextView android:id="#+id/text">
<ImageView android:id="#+id/icon>
</LinearLayout>
You'd then write a view
ToolbarView.java:
package com.example
public class ToolbarView extends View {
private ImageView back;
private TextView text;
private ImageView icon;
public ToolbarView(Context context, AttributeSet attrs) {
LayoutInflater.from(context).inflate(R.layout.toolbar, this)
back = findViewById(R.id.back)
text = findViewById(R.id.text)
//Same for all other views
}
public void setText(String text) {
text.setText(text)
}
public void setBackEnabled(boolean enabled) {
back.setVisibility(enabled ? VISIBLE : GONE)
}
public void setIcon(Drawable icon) {
if(icon == null) {
icon.setVisibility(GONE)
}
else {
icon.setVisibility(VISIBLE)
icon.setDrawable(icon)
}
}
After that, you can just put <com.example.Toolbar/> in your other layouts and it will embed the toolbar. You can get it via FindViewById and then call setText, setBackEnabled, etc.

Related

Replicating the drop-down ToolbarItem "More" in Xamarin.Forms

I am struggling how I could replicate the drop-down ToolbarItem from Xamarin.Forms when a ToolbarItem's order is set to Secondary for IOS, in order for it to look like it does for Android.
Here are some images to better explain what I am looking for:
How it works on Android:
Code:
ToolbarItem toolbarItem = new ToolbarItem()
{
Text = "ToolbarItem",
Order = ToolbarItemOrder.Secondary
};
Images on how it looks on Android:
Image showing the "More" icon
Image showing the "More" icon expanded to show more toolbar items
There is no default "More" icon on the toolbar when setting the Order to Secondary in iOS. Instead what happens, is that a bar below the navigation bar is created, which includes all of the toolbar items - something I do not wish to have for my Application.
This is an example of how it has been achieved before on IOS:
A screenshot I took from one of my Apps that implements this
effect
In native iOS, you can use UIPopoverController to achieve your effect. But please notice that this control can only be used in iPad.
Since you are using Xamarin.Forms, we can create a custom renderer in iOS platform to get this.
Firstly, create a page renderer to display the UIPopoverController. We can show it from a UIBarButtonItem or a UIView depending on your request. Here I use UIBarButtonItem like:
//I defined the navigateItem in the method ViewWillAppear
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
rightItem = new UIBarButtonItem("More", UIBarButtonItemStyle.Plain, (sender, args) =>
{
UIPopoverController popView = new UIPopoverController(new ContentViewController());
popView.PopoverContentSize = new CGSize(200, 300);
popView.PresentFromBarButtonItem(rightItem, UIPopoverArrowDirection.Any, true);
});
NavigationController.TopViewController.NavigationItem.SetRightBarButtonItem(leftItem, true);
}
Secondly, construct the content ViewController in the UIPopoverController(just like the secondary list in android):
public class ContentViewController : UIViewController
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
UITableView tableView = new UITableView(new CGRect(0, 0, 200, 300));
tableView.Source = new MyTableViewSource();
View.AddSubview(tableView);
}
}
public class MyTableViewSource : UITableViewSource
{
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(new NSString("Cell"));
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, new NSString("Cell"));
}
cell.TextLabel.Text = "Item" + indexPath.Row;
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return 10;
}
}
At last we can show it on the screen by calling PresentFromBarButtonItem.

Put text in "TOP BAR" 2 lines + image

I'm trying put text in to bar, I only put (buttons), I don't know if I can put text 2 lines + image.
Here are references as changing the color:
https://developer.android.com/training/basics/actionbar/styling.html
in this other picture is displayed, as you can put more text in the top bar
http://www.whatsapp.com/img/v3/es/s1-chat.png
Simply create your own view and set it for your ActionBar: setCustomView().
You cannot achieve what you want with the standard layout. For plenty of examples look here:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
// add the custom view to the action bar
actionBar.setCustomView(R.layout.actionbar_view);
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield);
search.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
Toast.makeText(MainActivity.this, "Search triggered",
Toast.LENGTH_LONG).show();
return false;
}
});
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM
| ActionBar.DISPLAY_SHOW_HOME);
}
}
Source: vogella.com
I don't think you can do it.
I'd advise you just to create a layout that would act like a top bar in your application.
This way you would be able to put there anything you want.
If you have more than one activity that needs to have this top bar, then use fragments instead of activities (to avoid your custom top bar from being animated when new activities are being opened).

how to get white background theme for android options menu?

In my android application I would like my options menu to have a white background so that my icons show up better, I have seen many apps that had this but I am unable to figure out how to get this done.
The answers int his link will probably help you. This site gives you answer in many ways, for example using android:state_pressed=true and other options too(selected, focused) in your menu item will show your background of your item in white color.
How to change the background color of the options menu?
I'm not a fan of the standard options menu at all that's why I ALWAYS create a customized menu with ViewStubs. Just create a new layout where you design your menu bar, integrate it with ViewStub in your layout files and let the menu slide in.
Sample java code:
public boolean onKeyDown( int keyCode, KeyEvent event ) {
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
mMenuPanel = ( ( ViewStub ) findViewById( R.id.stub_onoption ) ).inflate();
// initialize buttons of your menu layout and define setOnClickListener()
if( !menuVisible ) {
constants.showPanel( this, mMenuPanel, true );
menuVisible = true;
} else {
constants.hidePanel( this, mMenuPanel, true );
menuVisible = false;
}
return true;
default:
break;
}
}
public static void hidePanel( Context context, View panel, boolean slideDown ) {
panel.startAnimation( AnimationUtils.loadAnimation( context, slideDown ? R.anim.slide_out : R.anim.slide_in_top ) );
panel.setVisibility( View.GONE );
}
public static void showPanel( Context context, View panel, boolean slideUp ) {
panel.startAnimation( AnimationUtils.loadAnimation( context, slideUp ? R.anim.slide_in : R.anim.slide_out_top ) );
panel.setVisibility( View.VISIBLE );
}
This way you'll be able to fully customize your menu bar (background buttons etc.)
Edit: This is just the rough idea how to do it. And if you're doing it for the first time it might be a little bit overweight just for changing the background color but You'll be able to use this concept later on in various occasions like different slide in effects, adjusting the menu design according to your application design, change location, size and many more things.
Furthermore this kind of concept can also be used for optional search bars, or in-app notifications (if you don't want to use a dialog). So it's definitely worth looking into it.

Creating custom components using regular android components

basically I want to encapsulate a simple component from code that I already have.
Basically it's a LinearLayout with buttons inside. These buttons will make changes to a ListView, and there is also some other small stuff that it will do.
Currently I have a XML layout with those, and I programmatically setup everything else: the buttons, the interaction between the list and the other small stuff.
Obviously I thought to myself, let's encapsulate this.
I started out trying to extend the LinearLayout and adding the buttons.
Already I have no idea how to inflate the buttons to add to the view
What method do I override to create this buttons just before the view gets created without messing with the measures and inflations, etc.
I've looked around but the custom components I see are either completely new components or components that simply add small functionality to the custom ones.
Is there some guidelines for doing this?
Good tutorials/examples?
Any help is appreciated. Thanks !
EDIT:
Okay, here is a little more specific stuff.
Basically I want to create a View that holds filter buttons for a ListView. This will be used in different places with different filters, so I need flexibility for the buttons.
Basically I'd like to do something like this:
CustomView view = new CustomView(activity);
view.addButton("Lala", new OnFilterClickListener {
onClick(ListView list, View v) {
// Do the filtering
}
});
mListView.addHeaderView(view);
I want the view to adapt it's weights for showing the buttons, show the user which filter is active, stuff like that.
But I still don't really know how to make those dynamically added buttons appear, where do I generate them, how to inflate them and stuff like that.
public class myLayout extends LinearLayout {
//...
public void addButton(String text, OnClickListener listener) {
Button newButton = new Button(mContext);
newButton.setText(text);
newButton.setOnClickListener(listener);
//Say we want the weights to be equal
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.Fill_PARENT, 1);
addView(newButton, params);
}
//...
}
You can even do something to the view before dispatching the click like this:
public class myLayout extends LinearLayout {
//...
public void addButton(String text, final OnClickListener listener) {
Button newButton = new Button(mContext);
newButton.setText(text);
newButton.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
//do whatever you want
//like change background of button or something
//finally
listener.onClick(v);
}
});
//Say we want the weights to be equal
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0,LinearLayout.LayoutParams.Fill_PARENT, 1);
addView(newButton, params);
}
//...
}

Honeycomb - customize SearchView inside the action bar

I have a field where the user can type a search query in the action bar of the application. This is declared in the action bar using a menu inflate in the Activity:
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item
android:id="#+id/action_search"
android:showAsAction="ifRoom"
android:actionViewClass="android.widget.SearchView"
android:title="#string/search"
></item>
</menu>
I need to customize the appearance of the SearchView (for instance background and text color). So far I could not find a way to do it using XML (using styles or themes).
Is my only option to do it in the code when inflating the menu?
Edit #1: I have tried programmatically but I cannot get a simple way to set the text color. Plus when I do searchView.setBackgroundResource(...) The background is set on the global widget, (also when the SearchView is iconified).
Edit #2: Not much information on the Search Developer Reference either
Seibelj had an answer that is good if you want to change the icons. But you'll need to
do it for every API version. I was using ICS with ActionBarSherlock and it didn't do justice for me but it did push me in the correct direction.
Below I change the text color and hint color. I showed how you might go about changing the
icons too, though I have no interest in that for now (and you probably want to use the default icons anyways to be consistent)
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// Set up the search menu
SearchView searchView = (SearchView)menu.findItem(R.id.action_search).getActionView();
traverseView(searchView, 0);
return true;
}
private void traverseView(View view, int index) {
if (view instanceof SearchView) {
SearchView v = (SearchView) view;
for(int i = 0; i < v.getChildCount(); i++) {
traverseView(v.getChildAt(i), i);
}
} else if (view instanceof LinearLayout) {
LinearLayout ll = (LinearLayout) view;
for(int i = 0; i < ll.getChildCount(); i++) {
traverseView(ll.getChildAt(i), i);
}
} else if (view instanceof EditText) {
((EditText) view).setTextColor(Color.WHITE);
((EditText) view).setHintTextColor(R.color.blue_trans);
} else if (view instanceof TextView) {
((TextView) view).setTextColor(Color.WHITE);
} else if (view instanceof ImageView) {
// TODO dissect images and replace with custom images
} else {
Log.v("View Scout", "Undefined view type here...");
}
}
adding my take on things which is probably a little more efficient and safe across different android versions.
you can actually get a numeric ID value from a string ID name. using android's hierarchyviewer tool, you can actually find the string IDs of the things you are interested in, and then just use findViewById(...) to look them up.
the code below sets the hint and text color for the edit field itself. you could apply the same pattern for other aspects that you wish to style.
private static synchronized int getSearchSrcTextId(View view) {
if (searchSrcTextId == -1) {
searchSrcTextId = getId(view, "android:id/search_src_text");
}
return searchSrcTextId;
}
private static int getId(View view, String name) {
return view.getContext().getResources().getIdentifier(name, null, null);
}
#TargetApi(11)
private void style(View view) {
ImageView iv;
AutoCompleteTextView actv = (AutoCompleteTextView) view.findViewById(getSearchSrcTextId(view));
if (actv != null) {
actv.setHint(getDecoratedHint(actv,
searchView.getContext().getResources().getString(R.string.titleApplicationSearchHint),
R.drawable.ic_ab_search));
actv.setTextColor(view.getContext().getResources().getColor(R.color.ab_text));
actv.setHintTextColor(view.getContext().getResources().getColor(R.color.hint_text));
}
}
You can use the attribute android:actionLayout instead which lets you specify a layout to be inflated. Just have a layout with your SearchView and you won't have to modify anything really.
As to changing text style on the SearchView that is probably not possible as the SearchView is a ViewGroup. You should probably try changing text color via themes instead.
In case anyone wants to modify the views directly, here is how you can change the colors/fonts/images and customize the search box to your pleasure. It is wrapped in a try/catch in case there are differences between versions or distributions, so it won't crash the app if this fails.
// SearchView structure as we currently understand it:
// 0 => linearlayout
// 0 => textview (not sure what this does)
// 1 => image view (the search icon before it's pressed)
// 2 => linearlayout
// 0 => linearlayout
// 0 => ImageView (Search icon on the left of the search box)
// 1 => SearchView$SearchAutoComplete (Object that controls the text, subclass of TextView)
// 2 => ImageView (Cancel icon to the right of the text entry)
// 1 => linearlayout
// 0 => ImageView ('Go' icon to the right of cancel)
// 1 => ImageView (not sure what this does)
try {
LinearLayout ll = (LinearLayout) searchView.getChildAt(0);
LinearLayout ll2 = (LinearLayout) ll.getChildAt(2);
LinearLayout ll3 = (LinearLayout) ll2.getChildAt(0);
LinearLayout ll4 = (LinearLayout) ll2.getChildAt(1);
TextView search_text = (TextView) ll3.getChildAt(1);
search_text.setTextColor(R.color.search_text);
ImageView cancel_icon = (ImageView)ll3.getChildAt(2);
ImageView accept_icon = (ImageView)ll4.getChildAt(0);
cancel_icon.setBackgroundDrawable(d);
accept_icon.setBackgroundDrawable(d);
} catch (Throwable e) {
Log.e("SearchBoxConstructor", "Unable to set the custom look of the search box");
}
This example shows changing the text color and the background colors of the cancel/accept images. searchView is a SearchView object already instantiated with it's background color:
Drawable d = getResources().getDrawable(R.drawable.search_widget_background);
searchView.setBackgroundDrawable(d);
Here is the drawable code:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#color/white" />
</shape>
Obviously, this is hacky, but it will work for now.
From ICS this is doable using themes and styles. I'm using ActionBarSherlock which makes it applicable also for HC and below.
Add a style to define "android:textColorHint":
<style name="Theme.MyHolo.widget" parent="#style/Theme.Holo">
<item name="android:textColorHint">#color/text_hint_corp_dark</item>
</style>
Apply this as "actionBarWidgetTheme" to your theme:
<style name="Theme.MyApp" parent="#style/Theme.Holo.Light.DarkActionBar">
...
<item name="android:actionBarWidgetTheme">#style/Theme.MyHolo.widget</item>
</style>
Presto! Make sure that you use getSupportActionBar().getThemedContext() (or getSupportActionBar() for ActionBarSherlock) if any widgets are initiated where you might have other themes in effect.
How do you inflate the menu xml in your Activity? if you inflate the menu by using getMenuInflator() in your Activity, then the menu and also the searchView get the themed context, that have attached to the activity.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater.inflate(R.menu.search_action_menu, menu);
}
if you check the source code of Activity.getMenuInflator() at API-15, you can see the themed context codes. Here it is.
*/
public MenuInflater getMenuInflater() {
// Make sure that action views can get an appropriate theme.
if (mMenuInflater == null) {
initActionBar();
if (mActionBar != null) {
mMenuInflater = new MenuInflater(mActionBar.getThemedContext());
} else {
mMenuInflater = new MenuInflater(this);
}
}
return mMenuInflater;
}

Categories

Resources