I have a RecyclerView with a fixed Dimension-Ratio
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
...>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintDimensionRatio="35:16"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
I Need to show list of ImageView inside the RecyclerView, but with a fixed number of images shown on the screen, and the rest of the images need to scroll to be shown, similar to the image
I Create this layout with ImageView inside it:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="#drawable/image2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
The problem here
I try a lot, but the image doesn't show without setting the layout_width and layout_hieght with a fixed number.
and What i want is to set ImageView hight-width dynamicly with RecyclerView Hight and Screen Width.
The solution is super easy:
pass DisplayMetrics In The Adapter Constructor for getting screen width.
DisplayMetrics displayMetrics;
public SearchSliderOneAdapter(DisplayMetrics displayMetrics) {
this.displayMetrics = displayMetrics;
}
and calculate the width of ImageView = ScreenWidth\numberOfImage inside onCreateViewHolder function of the adapter.
public SearchSliderOneViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_slider, parent, false);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
displayMetrics.widthPixels / numberOfImage,
GridLayout.LayoutParams.MATCH_PARENT, 1);
inflate.setLayoutParams(params);
return new SearchSliderOneViewHolder(inflate, listener);
}
Related
I'm trying to make Recyclerview like Shareit app. It uses sticky header and something like Cardview. I searched and found somethings for implementing sticky header with itemdecoration and it's okay. But for Cardview part, I tried to make nested Recyclerview but performance was so bad, Because using two vertical Recyclerview is not good at all. Is there any better way to achieve this?
The problem with performance is for when i scroll down. It makes lag on creating second item in parent Recyclerview.
AppheaderAdapter:
#Override
public AppHeaderAdapter.HeaderHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_media_header, parent, false);
HeaderHolder headerHolder = new HeaderHolder(view);
return headerHolder;
}
class HeaderHolder extends RecyclerView.ViewHolder { //story
final ImageView arrow;
final TextView tarikh;
final TextView tedad;
final CheckBox tick;
final RecyclerView item_recyc;
HeaderHolder(View itemView) {
super(itemView);
arrow = itemView.findViewById(R.id.header_arrow);
tarikh = itemView.findViewById(R.id.header_tarikh);
tedad = itemView.findViewById(R.id.header_tedad);
tick = itemView.findViewById(R.id.header_tick);
item_recyc = itemView.findViewById(R.id.header_recyc);
}
}
#Override
public void onBindViewHolder(#NonNull AppHeaderAdapter.HeaderHolder headerHolder, int position) {
final AppHeader appHeader = appHeaders.get(position);
...
GridLayoutManager gridLayoutManager = new GridLayoutManager(context, span);
gridLayoutManager.setRecycleChildrenOnDetach(true);
headerHolder.item_recyc.setLayoutManager(gridLayoutManager);
headerHolder.item_recyc.setNestedScrollingEnabled(false);
AppItemAdapter adapter = new AppItemAdapter(context, appHeader.getAppList(), fr_parent, width);
headerHolder.item_recyc.swapAdapter(adapter, true);
...
}
item_media_header.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/header_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#drawable/so_round_so_white"
app:cardCornerRadius="10dp"
app:cardElevation="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/header_arrow"
android:layout_width="30dp"
android:layout_height="30dp"
android:padding="8dp"
android:src="#drawable/header_arrow"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/header_tarikh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/fragment_file"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#id/header_arrow"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/header_tedad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="2dp"
android:textColor="#AAAAAA"
android:textSize="#dimen/fragment_file"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="#id/header_tarikh"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/header_tick"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:button="#null"
android:clickable="false"
android:drawableRight="#drawable/file_checkbox"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/header_recyc"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
EDIT 1:
I find that just first Cardview is loaded and second one is not loaded until I scroll to end of first one and then load second CardView item and it lags because of second RecyclerView.
I found that Shareit use previous created adapter and just change its internal datalist, So i do that, but still has lag on second item.
Edite 2:
I use one time created adapter on all RecyclerView but still has lag.
Edit 3:
It's a known bug that innerRecyclerView load all items at first and that cause my lag too. because inner Recyclerview is inside NestedScrollView (RV) and it loads all content.Using constant height doesn't work, But I'll update question if I find something better.
You can achieve this with ConstraintLayout and Flow.
EDIT: Sorry, I just realised I wrote everything in Kotlin. If you cannot understand something I can try to translate it to Java.
xml:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/constraintLayout"
...>
<androidx.constraintlayout.helper.widget.Flow
android:id="#+id/flow"
app:flow_wrapMode="aligned"
app:flow_horizontalStyle="spread_inside"
app:flow_maxElementsWrap="4"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Adding of items:
val constraintLayout = itemView.findViewById(R.id.constraintLayout)
val flow = itemView.findViewById(R.id.flow)
val items // items given to the viewHolder to display
val layoutInflater = LayoutInflater.from(context)
items.forEach { item ->
val view = // create item view, e.g. DataBinding, ...
view.id = ViewCompat.generateViewId()
constraintLayout.addView(root)
flow.addView(root)
}
}
// if there are less than 4 items you have to add invisible dummy items. Otherwise, the alignment will look different for these ViewHolders
if(items.size>=4) return
for (i in 0..(4-items.size)) {
val view = // create dummy view
view.id = ViewCompat.generateViewId()
constraintLayout.addView(root)
flow.addView(root)
}
So far, Using vertical RV inside vertical RV has bug. Because of inner RV make long height and outer RV has no idea of this, So it create just first Item, but all items in inner RV. using all solution on Stack O.F. had no effect!
I want to update the style of the selected item inside a ViewPager.
How can I do this?
This is the UI design. As you can see, the "November" tab is selected, so the corresponding bar is highlighted in yellow.
The way I've implemented this is a ViewPager with a custom item (white, not highlighted):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="142dp"
android:layout_height="275dp"
android:layout_margin="0dp"
app:cardElevation="0dp"
app:cardBackgroundColor="#android:color/transparent">
<TextView
android:id="#+id/monthly_spend_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/December"
android:textColor="#color/aluminum"
android:textSize="20sp"
android:textStyle="normal"
android:layout_marginStart="22dp"
android:layout_marginTop="34dp"/>
<RelativeLayout
android:id="#+id/monthly_spend_card"
android:layout_marginTop="120dp"
android:layout_marginStart="22dp"
android:layout_width="120dp"
android:layout_height="155dp"
android:background="#drawable/monthlyspend_card_bg_inactive">
<TextView
android:id="#+id/monthly_spend_text"
android:textColor="#color/almost"
android:layout_marginTop="50dp"
android:layout_marginStart="22dp"
android:text="Total
spent"
android:textSize="#dimen/balanceDescTextSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/monthly_spend_amount"
android:textColor="#color/almost"
android:layout_marginTop="10dp"
android:layout_marginStart="22dp"
android:layout_below="#id/monthly_spend_text"
android:text="$ 254.98"
android:textSize="#dimen/balanceDescTextSize"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
I plan on doing the highlighting programmatically.
Here's some adapter code:
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.monthlyspend_item, container, false);
TextView monthlySpendMonth, monthlySpendAmount;
monthlySpendCard = view.findViewById(R.id.monthly_spend_card);
monthlySpendMonth = view.findViewById(R.id.monthly_spend_month);
monthlySpendAmount = view.findViewById(R.id.monthly_spend_amount);
monthlySpendMonth.setText(monthlySpendings.get(position).getMonth());
monthlySpendAmount.setText(monthlySpendings.get(position).getAmountSpent());
container.addView(view, 0);
return view;
}
Any help would be appreciated!
I thing you are missing click listener :
view.setOnClickListener(new OnClickListener(){
public void onClick(View v){
// do you stuff here
}
});
((ViewPager)container).addView(view, 0)
Also inside instantiateItem() make int position as final.
you should change your model (in your case "monthlyspendings") at the selected item position.
then notify the adapter
adapter.notifyDataSetChanged()
and finally, custom selected view according to the model. for exapmle :
if(monthlySpendings.get(position).isSelected) monthlySpendCard.setBackgroundColor(Color.parseColor("#fcd14b"));
I have a fragment inside a ViewPager and am trying to dynamically change the height of a ListView depending on the size of the screen.
Here is the xml code for my fragment:
Fragment.xml
<RelativeLayout
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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<RelativeLayout
android:id="#+id/rlDiscoveredDevice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/tvSuggestBTOn">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvDiscoveredDevices"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:text="#string/text_list_discovered_devices"
/>
<ProgressBar
android:id="#+id/pbDiscoveredDevices"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#+id/tvDiscoveredDevices"
android:layout_marginStart="16dp"
/>
<ListView
android:id="#+id/lstDiscoveredBTDevices"
android:layout_height="250dp"
android:layout_width="wrap_content"
android:divider="#android:color/transparent"
android:dividerHeight="#dimen/list_view_divider_height"
android:choiceMode="singleChoice"
android:listSelector="#color/list_item_selected"
android:layout_below="#+id/tvDiscoveredDevices"
android:layout_marginTop="#dimen/list_view_margin_top"
/>
</RelativeLayout>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/pairBT"
android:background="#drawable/ic_action_down"
android:layout_marginStart="134dp"
android:layout_below="#+id/rlDiscoveredDevice"
android:layout_alignParentStart="true"
/>
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/unpairBT"
android:background="#drawable/ic_action_up"
android:layout_below="#+id/rlDiscoveredDevice"
android:layout_toEndOf="#+id/pairBT"
android:layout_marginStart="73dp"
/>
<RelativeLayout
android:id="#+id/rlPairedDevice"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/pairBT">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvPairedDevices"
android:text="#string/text_list_paired_devices"
android:layout_alignParentStart="true"
/>
<ListView
android:id="#+id/lstPairedBTDevices"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:divider="#android:color/transparent"
android:dividerHeight="#dimen/list_view_divider_height"
android:choiceMode="singleChoice"
android:listSelector="#color/list_item_selected"
android:layout_below="#+id/tvPairedDevices"
android:layout_alignParentStart="true"
android:layout_marginTop="#dimen/list_view_margin_top"
/>
</RelativeLayout>
</RelativeLayout>
Here is my java code that I use to dynamically change the height:
DiscoveredDevice.java
public class DiscoveredDevice extends Fragment{
final String TAG = "DiscoverDevice Fragment";
private SharedPreferences appPrefs;
private BTActions btActions;
private ArrayList<BluetoothDevice> arrDiscoveredDevicesList;
private Set<BluetoothDevice> arrPairedDevicesList;
private ArrayAdapter<String> btDiscListArrayAdapter;
private ArrayAdapter<String> btPairedListArrayAdapter;
private String strDiscoveredListItemSelected = "";
private String strPairedListItemSelected = "";
private CommonFunctions cf;
private boolean blnIsFragmentLoaded = false;
// UI Objects
private TextView tvDiscoveredDevices;
private TextView tvPairedDevices;
private ListView lvDiscoveredList;
private ListView lvPairedDevicesList;
private ImageButton ibtnPair;
private ImageButton ibtnUnPair;
private ProgressBar pbDiscDevicesSpinner;
private TextView tvSuggestBTOn;
private ProgressBar pbLoading;
public DiscoveredDevice() {
btActions = new BTActions();
cf = new CommonFunctions();
}
#Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "Begin render of Discovered Device fragment...");
super.onCreate(savedInstanceState);
// Define variables
appPrefs = this.getActivity().getPreferences(Context.MODE_PRIVATE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_discovered_device, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Define the lists on DiscoveredDevice fragment
btDiscListArrayAdapter = new ArrayAdapter<>(getContext(), R.layout.simple_row, R.id.simple_row_Txt);
btPairedListArrayAdapter = new ArrayAdapter<>(getContext(), R.layout.simple_row, R.id.simple_row_Txt);
// Define UI Objects
defineUIObjects();
// Position UI objects
positionUIObjects();
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
}
private void defineUIObjects() {
tvDiscoveredDevices = (TextView) getView().findViewById(R.id.tvDiscoveredDevices);
tvPairedDevices = (TextView) getView().findViewById(R.id.tvPairedDevices);
lvDiscoveredList = (ListView) getView().findViewById(R.id.lstDiscoveredBTDevices);
lvPairedDevicesList = (ListView) getView().findViewById(R.id.lstPairedBTDevices);
ibtnPair = (ImageButton) getView().findViewById(R.id.pairBT);
ibtnUnPair = (ImageButton) getView().findViewById(R.id.unpairBT);
tvSuggestBTOn = (TextView) getView().findViewById(R.id.tvSuggestBTOn);
pbDiscDevicesSpinner = (ProgressBar) getView().findViewById(R.id.pbDiscoveredDevices);
pbLoading = (ProgressBar) getView().findViewById(R.id.spin_kit_progress);
pbLoading.setIndeterminateDrawable(new DoubleBounce());
}
private void positionUIObjects() {
final ViewGroup vgDiscDevice = (ViewGroup) getView().findViewById(R.id.rlDiscoveredDevice);
final AtomicInteger aiLayoutHeight = new AtomicInteger();
Rect rect = new Rect();
// Get the window
Window win = getActivity().getWindow();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
// Find height of AppBarLayout
AppBarLayout ablTabs = (AppBarLayout) getActivity().findViewById(R.id.ablTabs);
// Obtain the screen height & width
DisplayMetrics metrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
int intScreenHeight = metrics.heightPixels;
int intScreenWidth = metrics.widthPixels;
Log.i(TAG, "Actual Screen Height = " + intScreenHeight + " Width = " + intScreenWidth);
// Set the height for Discovered Devices list
RelativeLayout.LayoutParams rlParams = (RelativeLayout.LayoutParams) getView().findViewById(R.id.rlDiscoveredDevice).getLayoutParams();
// Get height of Discovered Devices relative layout
int intDiscoveredDevicesRLHeight = (int)(Math.round((intScreenHeight - rect.top - ablTabs.getMeasuredHeight()) * 0.45));
Log.i(TAG, "Setting the height of Discovered Devices Relative layout as '" + intDiscoveredDevicesRLHeight + "'");
rlParams.topMargin = ablTabs.getMeasuredHeight();
rlParams.leftMargin = 50; // I DID THIS JUST TO CHECK IF THE LEFT MARGIN GETS MOVED TO THE RIGHT. THIS IS WHERE I NEED A BETTER WAY TO PROPERLY ALIGN THE LIST
rlParams.height = intDiscoveredDevicesRLHeight;
lvDiscoveredList.setLayoutParams(rlParams);
}
I want each list to occupy 45% of the screen(excluding the AppBarLayout). If you see the below screenshot, when I set the new height, the ListView goes out of alignment and part of it gets cuts to the left of the screen. I have set the Left margin to 50 to bring it into view.
[Screenshot]
I have placed 2 ListViews inside a RelativeLayouts so that they can be individually controlled as a whole. Am I doing something wrong here ?
I think you can achieve this with just xml, no dynamic resizing!
In your post you mentioned that you want the list views to each take 45% of the available height. Thus, I am assuming that the center content with the image views will take 10% of the height (though this approach will also work if they had a fixed height, I'll include that answer too at the bottom.
All you need to do is change your top level layout to a LinearLayout (with a vertical orientation), put your image views inside of a LinearLayout (with horizontal orientation), change some of the heights of your views and add layout_weight attributes to the two RelativeLayouts and the inner LinearLayout you will create. Here is an example of what your xml will look like:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<RelativeLayout
android:id="#+id/rlDiscoveredDevice"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_above="#+id/tvSuggestBTOn"
android:layout_weight="9">
<TextView
android:id="#+id/tvDiscoveredDevices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text="#string/text_list_discovered_devices"
/>
<ProgressBar
android:id="#+id/pbDiscoveredDevices"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_toEndOf="#+id/tvDiscoveredDevices"
/>
<ListView
android:id="#+id/lstDiscoveredBTDevices"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tvDiscoveredDevices"
android:divider="#android:color/transparent"
android:dividerHeight="#dimen/list_view_divider_height"
android:choiceMode="singleChoice"
android:listSelector="#color/list_item_selected"
android:background="#drawable/abc_list_selector_disabled_holo_dark"
/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:layout_weight="2">
<ImageButton
android:id="#+id/pairBT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_action_down"
/>
<ImageButton
android:id="#+id/unpairBT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_action_up"/>
</LinearLayout>
<RelativeLayout
android:id="#+id/rlPairedDevice"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tvPairedDevices"
android:text="#string/text_list_paired_devices"
android:layout_alignParentStart="true"
/>
<ListView
android:id="#+id/lstPairedBTDevices"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:divider="#android:color/transparent"
android:dividerHeight="#dimen/list_view_divider_height"
android:choiceMode="singleChoice"
android:listSelector="#color/list_item_selected"
android:layout_below="#+id/tvPairedDevices"
android:layout_alignParentStart="true"
android:background="#drawable/abc_list_selector_disabled_holo_dark"
/>
</RelativeLayout>
</LinearLayout>
The important thing to note here is that the RelativeLayouts now have a weight of 9 each and the center linear layout has a weight of 2. Thus the space in the top level linear layout will be divided in that ratio, the RelativeLayouts will get 45% each and the LinearLayout will get 10%.
If you wanted the linear layout in the center to be wrap content instead of taking 10% of the screen (I would recommend this) then you could go ahead and assign it a height of wrap_content and remove the layout_weight attribute from it. The top level LinearLayout will then take the leftover height after allocating space for the center LinearLayout and divide it evenly between the two Relative layouts.
PS: (Heads up, you can probably use the xml I posted here. I set backgrounds on the list views to make it easy for me to see their sizes without data, make sure to remove those).
PPS: Note that this approach allows you to remove a lot of the layout positioning attributes that you had with a top level relative layout! This not only improves the cleanliness of your code, but also makes your UI more performant (Relative Layouts are less performant than other view groups, especially when nested).
I am adding dynamic imagebuttons to a layout in a Fragment using recyclerview with gridlayoutmanager. The buttons are added as a user performs an action, so they are not all created during onCreateView().
I seem to have to initialize my recycler view and adapter onCreateView() with a an empty imagebutton, when my app starts up. And so I do that, but it creates a little grey square like the image below.
and then when the user performs an action and the real button I want is created, the square is still present over my image button that was just created like you can see in this new image below.
DOES ANYONE KNOW HOW I CAN GET THE INITIAL EMPTY GREY IMAGE BUTTON TO NOT BE THERE AT STARTUP OR OVER MY "DriveDroid" IMAGE BUTTON?
I have tried setting the initial background of my image button to transparent (using background color = #00000000), but this seems to make a transparent image button over my DriveDroid button, so that my onClick listener for DriveDroid no longer works.
Here is how I initialize my recycler view:
public class MyFragment extends Fragment {
private GridLayoutManager lLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.my_fragment, container, false);
// Create an empty list to initialize the adapter (or else get nullPointerException error)
List<ItemObject> myList = new ArrayList<ItemObject>();
lLayout = new GridLayoutManager(getActivity(), 4, GridLayoutManager.HORIZONTAL, false);
RecyclerView rView = (RecyclerView)view.findViewById(R.id.recycler_view);
rView.setHasFixedSize(true);
rView.setLayoutManager(lLayout);
RecyclerViewAdapter rcAdapter = new RecyclerViewAdapter(getActivity(),myList);
rView.setAdapter(rcAdapter);
return view;
}
And here is my layout my_fragment
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:layout_margin="5dp"
android:id="#+id/my_fragment"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="horizontal" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/new_app_button"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/new_app_name"
android:layout_below="#+id/new_app_button"
android:layout_alignStart="#+id/new_app_button"
android:layout_alignLeft="#+id/new_app_button"
android:gravity="center"
/>
</RelativeLayout>
HERE IS HOW I CHANGED MY LAYOUT TO GET IT TO WORK, IF IT HELPS ANYONE ELSE!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:layout_marginTop="15dp"
android:id="#+id/my_fragment"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scrollbars="horizontal" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/new_app_button"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/new_app_name"
android:gravity="center"
android:layout_below="#+id/new_app_button"
/>
</RelativeLayout>
</LinearLayout>
As mentioned in the comment, that your controls was overlapping each others, you should wrap them inside linear layout or add properties to make them positioned relative to each others.
Regarding the grey button this should be related to "new_app_button"
I have created a dropdown spinner with a background custom image. I have placed the spinner in a linear layout and I have aligned items using weight.
Here is my code -
XML -
<LinearLayout
android:id="#+id/csbar"
android:windowSoftInputMode="adjustPan"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:background="#101010"
android:layout_height="wrap_content">
<ImageButton
android:id="#+id/run"
android:layout_width="0dp"
android:layout_height="#dimen/height"
android:layout_weight="1"
android:background="#null"
android:contentDescription="#string/nul"
android:src="#drawable/ic_action_play" />
<ImageButton
android:id="#+id/save"
android:layout_width="0dp"
android:layout_height="#dimen/height"
android:layout_weight="1"
android:background="#null"
android:contentDescription="#string/nul"
android:src="#drawable/ic_action_save" />
<Spinner
android:id="#+id/more"
android:layout_width="0dp"
android:layout_weight="1"
android:background="#drawable/ic_action_sort_by_size"
android:layout_height="#dimen/height"/>
</LinearLayout>
Java -
int firstC = 0;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
/////I have removed rest of the code to make it more legible/////
Spinner more = (Spinner) rootView.findViewById(R.id.more);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.more, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
more.setAdapter(adapter);
more.setOnItemSelectedListener(this);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
((TextView)view).setText(null);
}
Here is the output -
As you can see the sort by size icon (icon on right) appears stretched.
How I want it to look like -
What is wrong with my code? Please help.
The background image takes all the given space - 1/3 of the the LinearLayout width. If you don’t want it to stretch, you could create a drawable layout, e.g. drawable/my_sort_icon:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/ic_action_sort_by_size"
android:tileMode="disabled"
android:gravity="center" />
and use it as a background image in your Spinner:
<Spinner
android:id="#+id/more"
android:layout_width="0dp"
android:layout_weight="1"
android:background="#drawable/my_sort_icon"
android:layout_height="#dimen/height"/>