Very simple question that doesn't need much code:
I'm using Android's default ActionBar (no Sherlock) in which I have a couple of MenuItems. One of them is a collapsible Action View (android:showAsAction="collapseActionView|always") for your typical search scenario: user clicks on the icon → a search box expands → when the user types anything onQueryTextChange does its magic).
SearchView sv = new SearchView(this);
sv.setLayoutParams(new ActionBar.LayoutParams(Gravity.RIGHT));
// Yada, yada...
sv.setOnQueryTextListener(new OnQueryTextListener() {
// The methods for onQueryTextSubmit and onQueryTextChange ... they apply filtering on the activity's list adapter and apparently work fine
}
menuItem.setActionView(sv); // menuItem is the item for the search action
searchAnswers.setOnActionExpandListener(new OnActionExpandListener() {
// The listener's methods for expand/collapse as I need some business logic behind them
}
All of the above works fine.
When the device is on portrait mode and has limited screen space, the SearchView occupies pretty much the whole action bar, hiding the other MenuItems (which have android:showAsAction="ifRoom") as well as the Activity's title, which is OK by me.
The problem is that if the device is on landscape mode (so that there's still free ActionBar space), the SearchView doesn't occupy the whole ActionBar (again, fine by me) but the Activity's title disappears (even though there's plenty of space where it could be displayed!). So my problem is that I get this empty space where the Activity's title could be shown.
Before expanding:
After expanding:
(Both screenshots are from a phone in landscape mode. Tested with Android 4.0.4 and 4.3.)
Any tips on how to keep the Activity's title when there's enough space?
Not sure if you found an answer to this problem yet. But I found an answer on this thread that may help - it certainly helped me.
ActionBar SearchView not fully expanding in landscape mode
Code copied from link:
searchView.setOnSearchClickListener(new OnClickListener() {
private boolean extended = false;
#Override
public void onClick(View v) {
if (!extended) {
extended = true;
LayoutParams lp = v.getLayoutParams();
lp.width = LayoutParams.MATCH_PARENT;
}
}
});
searchView.setMaxWidth(Integer.MAX_VALUE);
Building on CoolMind answer, it worked for me to set max width to a smaller value:
searchView.setMaxWidth(375);
setMaxWidth() interprets its parameter as pixels.
Related
This is my first Android project. I am working on an app for tracking courses in a degree program (this is the project for a course I'm taking). I have set a RecyclerView inside a fragment. At one point the loaded items were not displayed anymore. It was working previously. I only made some changes to other parts of the app, but none to this part. I see no reason for these items to not be showing. I feel like the problem started after I clicked "Install" on an emulator update, which Android Studio suggested. I suspect the update is causing the issue, but I don't know for certain.
The code snippet below is from my fragment. I have downloaded the SQLite database and confirmed that the course.getTermId() matches selectectTerm.getTermId() for 4 items. When I open the fragment, I see a toast message that says "4 Courses loaded", so I know the issue is not with my logic here. I have tried inserting both adapter.notifyDataSetChanged(); and recyclerView.invalidate(); on the blank line right before the toast, but the items still do not show up. I have checked my layout to ensure the RecyclerView is properly sized and anchored. There's clearly something I am missing, but I am simply not seeing it. I have also confirmed that my CourseFlatAdapter does not have any logic errors. No exceptions are printed in Logcat. Does anyone see anything I need to do to fix this?
RecyclerView recyclerView = getView().findViewById(R.id.recyclerCourses);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
recyclerView.setHasFixedSize(true);
CourseFlatAdapter adapter = new CourseFlatAdapter();
recyclerView.setAdapter(adapter);
courseViewModel = ViewModelProviders.of(this).get(CourseViewModel.class);
courseViewModel.getAllCourses().observe(this, new Observer<List<Course>>() {
#Override
public void onChanged(List<Course> courses) {
ArrayList<Course> filteredCourseList = new ArrayList<>();
for(Course course : courses){
if(course.getTermId() == selectectTerm.getTermId()){
filteredCourseList.add(course);
}
}
adapter.setCourses(filteredCourseList);
Toast.makeText(ViewTermFragment.this.getContext(), filteredCourseList.size() + " Courses loaded", Toast.LENGTH_SHORT).show();
}
});
I figured it out. One of the changes I had made was to put the fragment container in a ScrollView so the whole thing would be scrollable when there is a large amount of information. The RecyclerView was anchored to the bottom of the fragment and had the height set to MatchParent while the fragment's height was set to WrapContent so the RecyclerView ended having it's height calculated as 0 regardless of how many items it was displaying.
I changed the RecyclerView's height to WrapContent and removed the bottom anchor. It now works as expected. Thank you to everyone who may have spent time on this.
I have a swipe between tabs feature in an app I am developing using a FragmentPagerAdapter. My question is: how do I prevent the "can't go any further" animation for swiping at the first and last view?
So, say you have three tabs and you're already on the most far right tab. If you try to swipe right again, that gray/black shadow shows up, indicating that you can't go any further.
If you are using FragmentPagerAdapter then it is a default feature of FragmentPagerAdapter what you want.
you can use the below code to show the alert to user.
public void onPageScrollStateChanged(int state) {
int currentPage = pager.getCurrentItem(); //ViewPager Type
if (currentPage == 3 || currentPage == 0){
//Write your custom logic here.
}
}
Hope this will help to you.
I'm attempting to implement accessibility on a few custom views for an Android app.
I've condensed what is done in the Google Authenticator app with no luck:
public class CardView extends RelativeLayout {
// ...
#Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
event.setClassName(this.getClass().getName());
event.setPackageName(this.getContext().getPackageName());
event.getText().add("Card Test");
return true;
}
}
All TalkBack reports back is "Double-tap to select" when it's inside a ListView or ViewPager.
Does ViewPager override accessibility events?
What do I need to do in order to have TalkBack say "Card Test" inside ViewPagers and ListViews like I expect it to?
For current versions of Android, you need to set the content description of the view.
myView.setContentDescription("Card Test");
ListView and associated classes expect you to use the onItemSelectedListener instead of assigning an onClickListener to each View (and rightfully so).
If incorporating alanv's suggestion, try to convince android system to read out the content description
by either
If(accessibilityModeIsEnabled())//custom method that checks context.getSystemService(Context.ACCESSIBILITY_SERVICE).isEnabled()
myView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
or AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED.
or requestFocus
Above should done when myView is visible. May be during onMesasure when width and height are both positive
If list view is still unable to do so, then try doing the above tricks on the first element of list view. Accessibility in Android varies devices to device and not one strategy fits all
in an android app,
if you create a new project,
then automatically the 3 dot settings menu is created on phones where it is needed
and it is handled the same way as it would have in older versions by:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
if you create a custom title, you have to add the 3 dot menu yourself
how do I know when it is needed? meaning phones that don't have the settings button
also how do i create a context menu that is customized and attached to the 3 dot button
Edit:
after a disscusion with Shobhit Puri, I understood that I was not considering the actionbar, since I am using a minimum API 8, I don't have it,
so there is the option that CommonsWare just supplied to check if the settings menu exists (I still need to check if it exists in API 8)
Shobhit Puri's suggestion was:
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(...) ;
ActionBar ab = getActionBar();
ab.setTitle("My Title");
ab.setSubtitle("sub-title") ;
but that of cores requires API 11 or the support library V7
either way I am excepting Shobhit Puri's answer, because of all his help, and I will post my final solution when I know it works
also thanks to CommonsWare for a nice answer
Edit2:
I decided to go with CommonsWare solution for now, I wrote it like this:
if (android.os.Build.VERSION.SDK_INT >= 14) {
ViewConfiguration vc = ViewConfiguration.get(this);
if (!vc.hasPermanentMenuKey()) {
setting_dots.setVisibility(View.VISIBLE);
setting_dots.setOnClickListener(this);
registerForContextMenu(setting_dots);
}
}
ideally I think you should use the actionbar, because it provides you with most of the work, but it has a lot of compatability issues with API 8 which for now I would rather avoid
As #dumazy pointed out that the Action bar's Menu Overflow icon is only shown on those devices which do not have a hardware menu-button.
How do I know when it is needed? meaning phones that don't have the settings button
This is handled by Android itself. You don't need to worry.
how do i create a context menu that is customized and attached to the 3 dot button
You can just have a an xml file inside Menu folder in res. Then you can specify the xml file inside the MenuInflater. Eg:
lets name it list_menu.xml
?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#+id/menu_item_1"
android:title="#string/menu_string_1"
android:showAsAction="ifRoom|withText"/>
<item android:id="#+id/menu_item_1"
android:title="#string/menu_string_2"
android:showAsAction="ifRoom|withText"/>
</menu>
In the onCreateOptionsMenu you can set it as:
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater mi = getMenuInflater();
mi.inflate(R.menu.list_menu, menu);
return true;
}
This menu would be attached to the overflow-icon and have the items that you want to show when it is clicked. There are some hacks like this which can show the overflow-icon on all devices but using them is highly discouraged. Let android handle this itself.
You seem to use Title bar. Instead, try to use Action Bar for the same.
Hope this answers your question.
how do I know when it is needed? meaning phones that don't have the settings button
Call hasPermanentMenuKey() on a ViewConfiguration.
also how do i create a context menu that is customized and attached to the 3 dot button
By programming. Since you are not using an action bar, it is impossible to give you specific advice that would be relevant.
Google says Actionbar overflow only appears on phones that have no menu hardware keys. Phones with menu keys display the action overflow when the user presses the key.
If you still want to implement this you may follow this solution.
Click here for your reference.
Just copy this method in your activity and call the method from onCreate method
private void getOverflowMenu() {
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if(menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Is there any way to always show zoom controls in webview?
I found this: Always show zoom controls on a MapView
but that's for the mapview.
I want them to always be visible.
super.onCreate(savedInstanceState);
super.loadUrl("file:///android_asset/www/index.html");
WebSettings ws = super.appView.getSettings();
ws.setSupportZoom(true);
ws.setBuiltInZoomControls(true);
setDisplayZoomControls() is only available from API 11 (Android 3). So you can't even consider using it until the vast majority of Android devices are 3 or above - which will not be for some years :(
Not sure if this will work as I never tried, but I checked the reference in developer.android.com
ws.setDisplayZoomControls(true);
If this worked dont forget to best answer this answer.
Also check this out:
http://www.tutorialforandroid.com/2009/02/webview-with-zoomcontrols-in-android.html
good tutorial. (Debunks my theory)
None of the above worked for my. Only when I start draging the webview content the controls show up the first time. So what I did as a "quick fix" is in onStart() of my Fragment that holds the Dialog with the webview I call:
webview.invokeZoomPicker();
Example:
#Override
public void onStart(){
super.onStart();
DialogFragment dialog = this;
//...stuff
if(dialog.getDialog()!= null && dialog.getDialog().getWindow()!=null){
//...more stuff
View v = dialog.getView();
if(v!=null){
//invoke controls on start once, they stay active a few seconds:
WebView webview =v.findViewById(R.id.frag_dlg_WebView);
webview.invokeZoomPicker();
}
}
}
The controls light up only for a few seconds until they disappear again, by then the user in my case should have dragged the webview already.