I have the following list item that is used within a RecyclerView that has a vertical LinearLayout Manager. I am using espresso, and I would like to simulate clicking the id/action_save menu item. Below is my latest attempts at figuring this one out. I have tried using onData method combined with onChildView, but a MenuItem is not a View. The onView and withId methods works well if the menu item is located in a toolbar that is in the action bar, but while being embedded inside of a RecyclerView.
I have tried recording using the espresso recording feature in android studio, however, it inject code similar to this Espresso click menu item. When running the test case again causes the test to raise an exception.
List Item
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="0dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimaryDark"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
app:popupTheme="#style/MyDarkToolbarStyle"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ProgressBar
android:id="#+id/progress"
style="#style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true" />
<android.support.v7.widget.AppCompatImageView
android:id="#+id/imgPalette"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="250dp" />
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginTop="-2dp"
android:elevation="4dp"
android:outlineProvider="bounds"
android:paddingTop="2dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimaryDark">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</FrameLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
Menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/action_save"
android:title="#string/save"
app:showAsAction="never" />
</menu>
Main Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/banner" />
...
</RelativeLayout>
Java (Espresso / JUnit Test Case)
...
// mProducts is a list that is backed by the adapter and is of Type Product
for (int i = 0; i < mProducts.size(); i++) {
onView(allOf(withId(R.id.recyclerView), withParent(withId(R.id.container))))
.perform(actionOnItemAtPosition(i, clickOverflow(R.id.toolbar)));
// Add delay for system to respond to overflow being opened
SystemClock.sleep(1000);
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(i, clickMenuItem(R.id.toolbar, R.id.action_save)));
}
...
public static ViewAction clickMenuItem(final int toolbarId, final int id) {
return new ViewAction() {
#Override
public Matcher<View> getConstraints() {
return null;
}
#Override
public String getDescription() {
return "Click on a child view with specified id.";
}
#Override
public void perform(UiController uiController, View view) {
Toolbar toolbar = (Toolbar) view.findViewById(toolbarId);
for (int i = 0; i < toolbar.getChildCount(); i++) {
if (toolbar.getChildAt(i) instanceof ActionMenuView) {
ViewGroup viewGroup = ((ViewGroup) toolbar.getChildAt(i));
for (int j = 0; j < viewGroup.getChildCount(); j++) {
if (viewGroup.getChildAt(j).getId() == id) {
viewGroup.getChildAt(j).performClick();
break;
}
}
}
}
}
};
}
public static ViewAction clickOverflow(final int toolbarId) {
return new ViewAction() {
#Override
public Matcher<View> getConstraints() {
return null;
}
#Override
public String getDescription() {
return "Click on a child view with specified id.";
}
#Override
public void perform(UiController uiController, View view) {
Toolbar toolbar = (Toolbar) view.findViewById(toolbarId);
((ViewGroup) toolbar.getChildAt(0)).getChildAt(0).performClick();
}
};
}
Error
android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: com.variable.inspire:id/recyclerView
If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:android.support.v7.widget.MenuPopupWindow$MenuDropDownListView{92d26ac VFED.VC.. .F...... 0,0-515,252}
Update #1
This does not solve my question, but provides a workaround by displaying the menu item directly and not inside the overflow menu. My question still is using espresso can you open the overflow menu and click an item in it.
onView(allOf(withId(R.id.recyclerView), withParent(withId(R.id.container)))).perform(actionOnItemAtPosition(i, clickMenuItem(R.id.toolbar, R.id.action_save)));
Related
The following code is trivial but simulates the problem.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/btnGoToExtra"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="266dp"
android:text="Go To Extra"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
layout_extra.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btnBackToMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="186dp"
android:text="Back To Main"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btnGoToExtra)
.setOnClickListener(v -> {
setContentView(R.layout.layout_extra);
findViewById(R.id.btnBackToMain)
.setOnClickListener(vv -> {
setContentView(R.layout.activity_main);
});
});
}
}
Question
I can navigate to the layout_extra from activity_main and return to activity_main. Unfortunately, after this round trip, I can no longer be able to navigate to layout_extra anymore.
What causes this problem and how to fix it?
Explanation will follow in chat but that is not how it is supposed to be done, For views to change, You have other options like using Fragments or using new activity entirely, I would also like to suggest moving to kotlin.
public class MainActivity extends AppCompatActivity {
View mainView;
View extraView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainView = getLayoutInflater().inflate(R.layout.activity_main, null);
extraView = getLayoutInflater().inflate(R.layout.layout_extra, null);
setContentView(mainView);
mainView.findViewById(R.id.btnGoToExtra)
.setOnClickListener(v -> {
setContentView(extraView);
});
extraView.findViewById(R.id.btnBackToMain)
.setOnClickListener(vv -> {
setContentView(mainView);
});
}
}
Reading through the snippet above, here's how everything went
The line
findViewById(R.id.btnGoToExtra)
.setOnClickListener
Registers Button with id btnGoToExtra for click events and when that happens you have the nested
findViewById(R.id.btnBackToMain)
.setOnClickListener
Which registers the element with id backToMain for click events and that's all
Calling setContentView() multiple times is not recommended. The normal way to switch between layouts in the same activity is to use a ViewFlipper or FrameLayout
From here
You then have:
XML
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:src="#drawable/icon"
android:scaleType="fitCenter"
android:layout_height="fill_parent"
android:layout_width="fill_parent"/>
<TextView
android:text="Learn-Android.com"
android:textSize="24sp"
android:textColor="#000000"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:gravity="center"/>
</FrameLayout>
code
private void SwitchLayout2() {
RelativeLayout Layout1 = (RelativeLayout)findViewById(R.id.layout1);
RelativeLayout Layout2 = (RelativeLayout)findViewById(R.id.layout2);
// Enable Layout 2 and Disable Layout 1
Layout1 .setVisibility(View.GONE);
Layout2.setVisibility(View.VISIBLE);
}
private void SwitchLayout1() {
RelativeLayout Layout1 = (RelativeLayout)findViewById(R.id.layout1);
RelativeLayout Layout2 = (RelativeLayout)findViewById(R.id.layout2);
// Enable Layout 1 & Disable Layout2
Layout1.setVisibility(View.VISIBLE);
Layout2.setVisibility(View.GONE);
}
As you can see on the image below, I am having a hard time to figure out on how to deselect the first menu item since it is active by default on the BottomNavigationView.
I already tried everything but still the first menu is still raised.
Java Code.
public class MainActivity extends AppCompatActivity {
private BottomNavigationView bottomNavigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottomNavigationView = (BottomNavigationView)findViewById(R.id.bottomNavigation);
bottomNavigationView.setBackground(null);
bottomNavigationView.getMenu().setGroupCheckable(0, false, true);
bottomNavigationView.setElevation(0);
//bottomNavigationView.setSelectedItemId(R.id.menu2);
}
}
Main XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/main_bottom_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:fabCradleMargin="10dp"
app:fabCradleRoundedCornerRadius="10dp"
app:fabCradleVerticalOffset="10dp">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:background="#android:color/transparent"
app:menu="#menu/main_bottom_menu"
/>
</com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
app:backgroundTint="#color/_Surface"
app:tint="#color/_OnSurface"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#drawable/dashboard_24"
app:layout_anchor="#+id/main_bottom_appbar"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
If you have any ideas on how to normalize the menu items on the BottomNavigationView, I will really appreciate the help.
Thanks.
Try to add this in your bottomNavigationView in main.xml
app:labelVisibilityMode="unlabeled"
So your view will be like this:
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigation"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="16dp"
android:background="#android:color/transparent"
app:menu="#menu/main_bottom_menu"
app:labelVisibilityMode="unlabeled"
/>
You can see more details about what changes you are allowed to make on view here:
https://material.io/components/bottom-navigation/android#using-bottom-navigation
public static void setCheckable(BottomNavigationView view, boolean checkable) {
final Menu menu = view.getMenu();
for(int i = 0; i < menu.size(); i++) { // Your Menu 0
menu.getItem(i).setCheckable(checkable);
}
}
Since the related menu is 0, you can arrange the code according to 0.
I'm working an app that has a list of cardviews and I want each cardview to open a certain activity when tapped. I am not using any recyclerviews or adapters, I have just created a multiple cardview xml files and included them into my main xml in coordinatorlayout and collapsingtoolbarlayout. I have tried to create onClick event for individual cardviews but app keeps crashing.
Following is my main.xml code:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="250dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
android:background="#drawable/pic3"
android:id="#+id/profile_id"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="10dp">
<include layout="#layout/card_layout1" />
<include layout="#layout/card_layout6"/>
<include layout="#layout/card_layout4"/>
<include layout="#layout/card_layout5"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
One of my cardviews xml:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_alignParentTop="true"
android:src="#drawable/categories"
android:layout_marginTop="15dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"/>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/thumbnail"
android:maxLines="3"
android:padding="8dp"
android:text="Categories"
android:textColor="#color/white"
android:textSize="22dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/title"
android:maxLines="3"
android:padding="8dp"
android:text="Embedded systems is ba jksdhkah jksadh bdkbadkwuhs hfoh dn ajbd arh fbkjasd akuhwkjd nsajkbf a dsadjna hwd nlksn ahrja snasfb kjasba sna"
android:textColor="#color/white"
android:textSize="14dp" />
</RelativeLayout>
And my MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private CollapsingToolbarLayout collapsingToolbarLayout=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbarLayout.setTitle(getResources().getString(R.string.user_name));
dynamicToolbarColor();
toolbarTextAppearance();
}
private void dynamicToolbarColor() {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.elec);
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
#Override
public void onGenerated(Palette palette) {
int mutedColor = palette.getMutedColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary));
collapsingToolbarLayout.setContentScrimColor(mutedColor);
}
});
}
private void toolbarTextAppearance(){
collapsingToolbarLayout.setCollapsedTitleTextAppearance(R.style.collapsedbar);
collapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.expandedappbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
}
}
How can I implement onClick event for each of my cardviews without using recyclerview and adapters?
It's a bad practice. But you can set tag to all card views, find them in code and set click listener:
in you main.xml
...
<LinearLayout
android:id="#+id/cardsContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="10dp">
<include layout="#layout/card_layout1" />
<include layout="#layout/card_layout6"/>
<include layout="#layout/card_layout4"/>
<include layout="#layout/card_layout5"/>
</LinearLayout>
...
all in you card layouts must have tag:
<android.support.v7.widget.CardView
android:tag="clickableCard"
...>
...
</android.support.v7.widget.CardView>
Than you need to find all views with thos tag clickableCard : (solution from here: Find all views with tag?)
private ArrayList<View> getViewsByTag(ViewGroup root, String tag){
ArrayList<View> views = new ArrayList<View>();
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = root.getChildAt(i);
if (child instanceof ViewGroup) {
views.addAll(getViewsByTag((ViewGroup) child, tag));
}
final Object tagObj = child.getTag();
if (tagObj != null && tagObj.equals(tag)) {
views.add(child);
}
}
return views;
}
in you MainActivity.java in the end of onCreate method you need to:
ArrayList<View> clickableViews = getViewsByTag(findViewById(R.id.cardsContainer), "clickableCard");
for (int i = 0; i < clickableViews.size(); i++) {
final Integer viewIndex = i;
View cardView = clickableViews.get(i);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (viewIndex == 0) {
// do work with first card
}
else if (viewIndex == 1) {
// do work with second card
}
...
}
});
}
I'm developing a material design app. I want to display a list using RecyclerView in HelpActivity.
The problem is that I'm getting the following errors: java.lang.RuntimeException: java.lang.IllegalStateException: RecyclerView has no LayoutManager on line (HelpActivity.java:28).
Here's HelpActivity.java file's code:
public class HelpActivity extends AppCompatActivity {
public RecyclerView mRecyclerView;
public RecyclerView.LayoutManager mLayoutManager;
public RecyclerView.Adapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
mRecyclerView = (RecyclerView) findViewById(R.id.helpActivityContent);
// use a linear layout manager
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
mAdapter = new HelpContentAdapter(helpContents);
mRecyclerView.setAdapter(mAdapter);
initializeData();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitleTextColor(Color.parseColor("#2196F3"));
setSupportActionBar(toolbar);
/*final Drawable upArrow = ContextCompat.getDrawable(this, R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(upArrow);*/
/*FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});*/
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
class HelpActivityContent {
String option;
String subOption;
int icon;
HelpActivityContent(String option, String subOption, int icon) {
this.option = option;
this.subOption = subOption;
this.icon = icon;
}
}
public List<HelpActivityContent> helpContents;
// This method creates an ArrayList that has three Person objects
// Checkout the project associated with this tutorial on Github if
// you want to use the same images.
private void initializeData(){
helpContents = new ArrayList<>();
helpContents.add(new HelpActivityContent("123", "", R.drawable.ic_action_a));
helpContents.add(new HelpActivityContent("123", "", R.drawable.ic_action_b));
helpContents.add(new HelpActivityContent("321", "111", R.drawable.ic_action_c));
helpContents.add(new HelpActivityContent("1", "2", R.drawable.ic_action_d));
}
public class HelpContentAdapter extends RecyclerView.Adapter<HelpContentAdapter.HelpContentViewHolder>{
public class HelpContentViewHolder extends RecyclerView.ViewHolder {
TextView option;
TextView subOption;
ImageView icon;
HelpContentViewHolder(View itemView) {
super(itemView);
option = (TextView)itemView.findViewById(R.id.option);
subOption = (TextView)itemView.findViewById(R.id.subOption);
icon = (ImageView)itemView.findViewById(R.id.optionIcon);
}
}
List<HelpActivityContent> helpContents;
HelpContentAdapter(List<HelpActivityContent> helpContents){
this.helpContents = helpContents;
}
#Override
public int getItemCount() {
return helpContents.size();
}
#Override
public HelpContentViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.content_help, viewGroup, false);
HelpContentViewHolder pvh = new HelpContentViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(HelpContentViewHolder helpContentViewHolder, int i) {
helpContentViewHolder.option.setText(helpContents.get(i).option);
helpContentViewHolder.subOption.setText(helpContents.get(i).subOption);
helpContentViewHolder.icon.setImageResource(helpContents.get(i).icon);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
supportFinishAfterTransition();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Here's content_help.xml file's code:
<?xml version="1.0" encoding="utf-8"?>
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/helpActivityContent"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_help"
tools:context="com.abc.xyz.HelpActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/optionIcon"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/option"
android:layout_toRightOf="#+id/optionIcon"
android:layout_alignParentTop="true"
android:textSize="30sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/subOption"
android:layout_toRightOf="#+id/optionIcon"
android:layout_below="#+id/option"
/>
</RelativeLayout>
</android.support.v7.widget.RecyclerView>
I'm unable to figure out what the problem is.
Please let me know.
Thanks in advance.
You cannot put your child elements directly inside the recycler view.
You need to create separate row layout like the one you create in listview.
Just remove the xml code written inside recycler view and insert it inside row_layout xml file and then inflate that row layout file inside your adapter instead.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_help"
tools:context="com.abc.xyz.HelpActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/optionIcon"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/option"
android:layout_toRightOf="#+id/optionIcon"
android:layout_alignParentTop="true"
android:textSize="30sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/subOption"
android:layout_toRightOf="#+id/optionIcon"
android:layout_below="#+id/option"
/>
</RelativeLayout>
Just create separate file for row_layout containing above content and inflate it like below inside your oncreateviewholder:
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.**<new_layout_you_will_create>**, viewGroup, false);
I just made a small change in your content_help.xml and it works fine for me..
content_help.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_help"
tools:context="com.abc.xyz.HelpActivity">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/optionIcon"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/option"
android:layout_toRightOf="#+id/optionIcon"
android:layout_alignParentTop="true"
android:textSize="30sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/subOption"
android:layout_toRightOf="#+id/optionIcon"
android:layout_below="#+id/option"
/>
If you are using the recyclerview in activity_help.xml, no need to use the same for your row-content.
Hope this will solve your problem
I am creating tabs inside the fragment class. Right now i am showing two tabs in the fragment class. Everything works fine and tabs are shown properly. Only cache is that, the tabs shown only take half of the screen width, It doesn't take the full screen width.
So anyone tell me what i need to change in my code to achieve that
My Code
tabsinfo_fragment.xml file
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#EFEFEF" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none" >
<TabWidget
android:id="#android:id/tabs"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</HorizontalScrollView>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<FrameLayout
android:id="#+id/tab_1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<FrameLayout
android:id="#+id/tab_2"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
</LinearLayout>
</TabHost>
tab.xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="20dp"
android:background="#drawable/tab_selector">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#drawable/tab_text_selector"
android:textIsSelectable="false" />
</LinearLayout>
code inside fragment class
public class TabsInfoFragment extends Fragment implements OnTabChangeListener
{
private View m_Root;
private TabHost m_TabHost;
private int m_CurrentTab;
public String m_VisitorTabText;
public String m_FeedTabText;
public TabsInfoFragment()
{
}
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
m_VisitorTabText = Integer.toString(R.string.tab_visitor_text);
m_FeedTabText = Integer.toString(R.string.tab_feed_text);
m_Root = inflater.inflate(R.layout.tabsinfo_fragment, null);
m_TabHost = (TabHost) m_Root.findViewById(android.R.id.tabhost);
setupTabs();
return m_Root;
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
m_TabHost.setOnTabChangedListener(this);
m_TabHost.setCurrentTab(m_CurrentTab);
// Manually start loading stuff in the first tab
updateTab(m_VisitorTabText, R.id.tab_1, new ProfileInfoFragment());
}
private void setupTabs()
{
m_TabHost.setup();
m_TabHost.addTab(newTab(m_VisitorTabText, R.string.tab_visitor_text, R.id.tab_1));
m_TabHost.addTab(newTab(m_FeedTabText, R.string.tab_feed_text, R.id.tab_2));
}
private TabSpec newTab(String tag, int labelId, int tabContentId)
{
View indicator = LayoutInflater.from(getActivity()).inflate(R.layout.tab, (ViewGroup) m_Root.findViewById(android.R.id.tabs), false);
((TextView) indicator.findViewById(R.id.text)).setText(labelId);
TabSpec tabSpec = m_TabHost.newTabSpec(tag);
tabSpec.setIndicator(indicator);
tabSpec.setContent(tabContentId);
return tabSpec;
}
#Override
public void onTabChanged(String tabId)
{
if (m_VisitorTabText.equals(tabId))
{
updateTab(tabId, R.id.tab_1, new ProfileInfoFragment());
m_CurrentTab = 0;
return;
}
if (m_FeedTabText.equals(tabId))
{
updateTab(tabId, R.id.tab_2, new ProfileInfoFragment());
m_CurrentTab = 1;
return;
}
}
private void updateTab(String tabId, int placeholder, Fragment fragmentClass)
{
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag(tabId) == null)
{
fm.beginTransaction().replace(placeholder, fragmentClass, tabId).commit();
}
}
}
ScreenShot
The TabWidget class is a subclass of LinearLayout, so in the tab.xml file for the root xml element, in your case a LinearLayout, set the width to 0dp and the weight to 1, then all the tabs will be equal width. Like so:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="50dp"
android:gravity="center">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="This is a tab" />
</LinearLayout>
Try changing your TabWidget to this instead;
<TabWidget
android:id="#android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
try this
<TabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TabWidget
android:id="#android:id/tabs"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"/>
<FrameLayout
android:id="#android:id/tabcontent"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="0"/>
<FrameLayout
android:id="#+android:id/tab_1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<FrameLayout
android:id="#+android:id/tab_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</TabHost>
Try removing HorizontalScrollView and adding android:layout_width="fill_parent" to TabWidget
Need to add one single line
tabs.setDistributeEvenly(true);