I have a Layout like this:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="6dp"
android:id="#+id/shift_main_layout"
android:orientation="vertical"
android:background="#android:color/white">
<ScrollView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1">
<RelativeLayout
android:id="#+id/recycle_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="top">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/coworker_recycler"
android:layout_centerHorizontal="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
</ScrollView>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
<com.google.android.material.button.MaterialButton
android:id="#+id/remove_operator"
style="#style/customIconButton"
android:layout_width="wrap_content"
android:layout_height="25dp"
app:icon="#drawable/ic_remove_black_24dp" />
<com.google.android.material.button.MaterialButton
android:id="#+id/add_operator"
style="#style/customIconButton"
android:layout_width="wrap_content"
android:layout_height="25dp"
app:icon="#drawable/ic_add_black_24dp" />
</LinearLayout>
The items of the Recycler Viewer coworker_recycler are like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:paddingStart="0.5dp"
android:paddingEnd="0.5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/shift_layout">
<!--region Cells-->
<!--Ora00 Row-->
<TextView
android:id="#+id/ora00"
style="#style/cell_style"/>
<!--Ora01 Row-->
<TextView
android:id="#+id/ora01"
style="#style/cell_style"/>
<!--Ora02 Row-->
<TextView
android:id="#+id/ora02"
style="#style/cell_style"/>
<!--Ora03 Row-->
<TextView
android:id="#+id/ora03"
style="#style/cell_style"/>
<!--Ora04 Row-->
<TextView
android:id="#+id/ora04"
style="#style/cell_style"/>
<!--Ora05 Row-->
<TextView
android:id="#+id/ora05"
style="#style/cell_style"/>
<!--Ora06 Row-->
<TextView
android:id="#+id/ora06"
style="#style/cell_style"/>
<!--Ora07 Row-->
<TextView
android:id="#+id/ora07"
style="#style/cell_style"/>
<!--Ora08 Row-->
<TextView
android:id="#+id/ora08"
style="#style/cell_style"/>
<!--Ora09 Row-->
<TextView
android:id="#+id/ora09"
style="#style/cell_style"/>
<!--Ora10 Row-->
<TextView
android:id="#+id/ora10"
style="#style/cell_style"/>
<!--Ora11 Row-->
<TextView
android:id="#+id/ora11"
style="#style/cell_style"/>
<!--Ora12 Row-->
<TextView
android:id="#+id/ora12"
style="#style/cell_style"/>
<!--Ora13 Row-->
<TextView
android:id="#+id/ora13"
style="#style/cell_style"/>
<!--Ora14 Row-->
<TextView
android:id="#+id/ora14"
style="#style/cell_style"/>
<!--Ora15 Row-->
<TextView
android:id="#+id/ora15"
style="#style/cell_style"/>
<!--Ora16 Row-->
<TextView
android:id="#+id/ora16"
style="#style/cell_style"/>
<!--Ora17 Row-->
<TextView
android:id="#+id/ora17"
style="#style/cell_style"/>
<!--Ora18 Row-->
<TextView
android:id="#+id/ora18"
style="#style/cell_style"/>
<!--Ora19 Row-->
<TextView
android:id="#+id/ora19"
style="#style/cell_style"/>
<!--Ora20 Row-->
<TextView
android:id="#+id/ora20"
style="#style/cell_style"/>
<!--Ora21 Row-->
<TextView
android:id="#+id/ora21"
style="#style/cell_style"/>
<!--Ora22 Row-->
<TextView
android:id="#+id/ora22"
style="#style/cell_style"/>
<!--Ora23 Row-->
<TextView
android:id="#+id/ora23"
style="#style/cell_style"/>
<!--endregion-->
</LinearLayout>
</LinearLayout>
and the cell style of the items TextView is:
<style name="cell_style" parent="android:Widget.TextView">
<item name="android:layout_marginTop">1dp</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_gravity">center_horizontal</item>
<item name="android:layout_height">#dimen/cell_height</item>
</style>
The adapter of the Recycler Viewer is:
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.hearth.Model.ShiftModel;
import com.example.hearth.R;
import com.example.hearth.ViewHolder.ShiftViewHolder;
import com.squareup.picasso.Picasso;
import java.util.List;
import jp.wasabeef.picasso.transformations.CropCircleTransformation;
public class ShiftMapAdapter extends RecyclerView.Adapter {
private Context context;
private List<ShiftModel> shiftModelList;
int operatorShow;
private int Hour(double ora) {
return ora == 0 ? R.drawable.hour_empty : (ora == 0.5 ? R.drawable.hour_half : R.drawable.hour_full);
}
public ShiftMapAdapter(Context context, List<ShiftModel> shiftModelList, int operatorShow) {
this.context = context;
this.shiftModelList = shiftModelList;
this.operatorShow = operatorShow;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).inflate(R.layout.layout_shift_container, parent, false);
GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams)itemView.getLayoutParams();
float itemWidth = pxToDp(parent.getMeasuredWidth());
lp.width = dpToPx((itemWidth)/operatorShow);
itemView.setLayoutParams(lp);
return new ShiftViewHolder(itemView);
}
public int dpToPx(float dp) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
public float pxToDp(float px) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dp = px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT);
return dp;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
ShiftViewHolder vh = (ShiftViewHolder)holder;
Handler myHandler = new Handler();
myHandler.post(() -> {
vh.ora00.setBackgroundResource(Hour(shiftModelList.get(position).getOra00()));
vh.ora01.setBackgroundResource(Hour(shiftModelList.get(position).getOra01()));
vh.ora02.setBackgroundResource(Hour(shiftModelList.get(position).getOra02()));
vh.ora03.setBackgroundResource(Hour(shiftModelList.get(position).getOra03()));
vh.ora04.setBackgroundResource(Hour(shiftModelList.get(position).getOra04()));
vh.ora05.setBackgroundResource(Hour(shiftModelList.get(position).getOra05()));
vh.ora06.setBackgroundResource(Hour(shiftModelList.get(position).getOra06()));
vh.ora07.setBackgroundResource(Hour(shiftModelList.get(position).getOra07()));
vh.ora08.setBackgroundResource(Hour(shiftModelList.get(position).getOra08()));
vh.ora09.setBackgroundResource(Hour(shiftModelList.get(position).getOra09()));
vh.ora10.setBackgroundResource(Hour(shiftModelList.get(position).getOra10()));
vh.ora11.setBackgroundResource(Hour(shiftModelList.get(position).getOra11()));
vh.ora12.setBackgroundResource(Hour(shiftModelList.get(position).getOra12()));
vh.ora13.setBackgroundResource(Hour(shiftModelList.get(position).getOra13()));
vh.ora14.setBackgroundResource(Hour(shiftModelList.get(position).getOra14()));
vh.ora15.setBackgroundResource(Hour(shiftModelList.get(position).getOra15()));
vh.ora16.setBackgroundResource(Hour(shiftModelList.get(position).getOra16()));
vh.ora17.setBackgroundResource(Hour(shiftModelList.get(position).getOra17()));
vh.ora18.setBackgroundResource(Hour(shiftModelList.get(position).getOra18()));
vh.ora19.setBackgroundResource(Hour(shiftModelList.get(position).getOra19()));
vh.ora20.setBackgroundResource(Hour(shiftModelList.get(position).getOra20()));
vh.ora21.setBackgroundResource(Hour(shiftModelList.get(position).getOra21()));
vh.ora22.setBackgroundResource(Hour(shiftModelList.get(position).getOra22()));
vh.ora23.setBackgroundResource(Hour(shiftModelList.get(position).getOra23()));
});
}
#Override
public int getItemCount() {
return shiftModelList.size();
}
}
I use operatorShow in the onCreateViewHolder method to set the width of the items = 1/6 of the device's screen.
the view holder is:
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.hearth.R;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class ShiftViewHolder extends RecyclerView.ViewHolder {
Unbinder unbinder;
#BindView(R.id.ora00)
public
TextView ora00;
#BindView(R.id.ora01)
public
TextView ora01;
#BindView(R.id.ora02)
public
TextView ora02;
#BindView(R.id.ora03)
public
TextView ora03;
#BindView(R.id.ora04)
public
TextView ora04;
#BindView(R.id.ora05)
public
TextView ora05;
#BindView(R.id.ora06)
public
TextView ora06;
#BindView(R.id.ora07)
public
TextView ora07;
#BindView(R.id.ora08)
public
TextView ora08;
#BindView(R.id.ora09)
public
TextView ora09;
#BindView(R.id.ora10)
public
TextView ora10;
#BindView(R.id.ora11)
public
TextView ora11;
#BindView(R.id.ora12)
public
TextView ora12;
#BindView(R.id.ora13)
public
TextView ora13;
#BindView(R.id.ora14)
public
TextView ora14;
#BindView(R.id.ora15)
public
TextView ora15;
#BindView(R.id.ora16)
public
TextView ora16;
#BindView(R.id.ora17)
public
TextView ora17;
#BindView(R.id.ora18)
public
TextView ora18;
#BindView(R.id.ora19)
public
TextView ora19;
#BindView(R.id.ora20)
public
TextView ora20;
#BindView(R.id.ora21)
public
TextView ora21;
#BindView(R.id.ora22)
public
TextView ora22;
#BindView(R.id.ora23)
public
TextView ora23;
public ShiftViewHolder(#NonNull View itemView) {
super(itemView);
unbinder = ButterKnife.bind(this, itemView);
}
}
I call everything like this in a fragment:
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
shiftsViewModel = ViewModelProviders.of(this).get(ShiftsViewModel.class);
selectedDate = "2019-11-12";
setHasOptionsMenu(true);
View root = inflater.inflate(R.layout.fragment_shifts, container, false);
unbinder = ButterKnife.bind(this, root);
//Count how many columns are created in the recycle
addOperator.setOnClickListener(view -> {
int adapterItemsCount = shiftMapAdapter.getItemCount();
if (operatorShow < adapterItemsCount) {
operatorShow++;
getMap(selectedDate);
}
else {
Toast.makeText(getContext(), "Can't add more columns", Toast.LENGTH_SHORT).show();
}
});
removeOperator.setOnClickListener(view -> {
if (operatorShow > 5) {
operatorShow--;
getMap(selectedDate);
}
else {
Toast.makeText(getContext(), "Can't remove more columns", Toast.LENGTH_SHORT).show();
}
});
initialize();
getMap(selectedDate);
return root;
}
private void getMap(String selectedDate) {
shiftsViewModel.getCoworkerList(selectedDate).observe(getActivity(), shiftModel -> {
shiftMapAdapter = new ShiftMapAdapter(ShiftsFragment.this.getContext(), shiftModel, operatorShow);
coworker_recycler.setAdapter(shiftMapAdapter);
coworker_recycler.setLayoutAnimation(layoutAnimationController);
});
}
private void initialize() {
layoutAnimationController = AnimationUtils.loadLayoutAnimation(getContext(), R.anim.layout_item_from_left);
coworker_recycler.setHasFixedSize(true);
coworker_recycler.setLayoutManager(new GridLayoutManager(getContext(), 1, RecyclerView.HORIZONTAL, false));
}
The problem is that when I need to add more columns, for example, 8, the items do not expand correctly.
It's noticeable that there are some green pixels on the right edge like the picture.
Any help what I'm doing wrong, or any suggestion in a better way to expand equally the items of the RecyclerViewer?
float itemWidth = pxToDp(parent.getMeasuredWidth());
lp.width = dpToPx((itemWidth)/operatorShow);
When you divide itemWidth by operatorShow the answer will most likely be a fraction depending on screen width. Since the width is in Integers, you lose precision.'.
I'll explain it here if the above didn't make sense:
More detailed explanation:
Let's suppose width to be 640, and if your column count is 6 then:
itemWidth = 640/6 = 106.6666 = 106 (fractional part dropped since pixel is the smallest unit)
Now for each item, you width is exactly 106. Now let's calculate how much space all 6 columns would take if each took 106:
106 * 6 = 636 //Notice that our actual width was 640 so we lost 4 pixels in precision
As you can see, since we dropped the fractional part, we lost 4 precision. These 4 pixels are left out at the end and that's why you see the next columns when the view tries to fill the empty space.
What to do about it?
You can reduce the number of columns to a factor of device width, like in above example, if dividing by 6 makes a fraction then try with 5 and keep going lower until you find one.
If this breaks the functionality of the app, I'm afraid there is no helping it since pixels/dps can't be fractions.
Related
My goal is to dynamically create a grid of TextViews in a ConstraintLayout. I've seen many examples but there's an issue that I'm just not seeing. I've broken the task into two steps:
creating the View
positioning the View
I seem to have mastered the first but not the second. Usually I can modify a View's ConstraintSet if it is defined in XML and positioned at startup, but never when I've created it programmatically. When I create a View I'm careful to set an id, layout_width and layout_height. Method's I've tried for creating a new View:
creating it and setting parameters from a new LayoutParameters object
creating it and setting parameters from another View.
inflating it from an XML template.
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"
android:id="#+id/activity_main" >
<Button
android:id="#+id/makeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10sp"
android:text="Make View"
android:onClick="makeView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="#+id/placeView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10sp"
android:text="Place View"
android:onClick="placeView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="#+id/makeView" />
<TextView
android:id="#+id/anchorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20sp"
android:layout_marginStart="20sp"
android:text="View 00"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package com.example.textviewonthefly;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
final String TAG = "DEBUGME";
final int START = ConstraintSet.START;
final int END = ConstraintSet.END;
final int TOP = ConstraintSet.TOP;
int counter = 0;
View anchorView;
TextView nextView;
ConstraintLayout mainLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainLayout = (ConstraintLayout) findViewById(R.id.activity_main);
anchorView = (TextView) findViewById(R.id.anchorView);
}
public void makeView(View view) {
nextView = new TextView(this);
nextView.setLayoutParams(anchorView.getLayoutParams());
int nextViewId = nextView.generateViewId();
nextView.setId(nextViewId);
int ViewCount = ++counter;
String newName = String.format(Locale.US, "View %02d", ViewCount);
nextView.setText(newName);
this.mainLayout.addView(nextView);
}
public void placeView(View view) {
ConstraintSet set = new ConstraintSet();
set.clone(this.mainLayout);
set.clear(nextView.getId());
set.connect(nextView.getId(), TOP, anchorView.getId(), TOP);
set.connect(nextView.getId(), START, anchorView.getId(), END);
set.applyTo(this.mainLayout);
anchorView = nextView;
}
}
Solved.
clear(nextView.getId()); was too aggressive. I replaced that line with more specific directives:
clear(nextView.getId(), END);
clear(nextView.getId(), BOTTOM);
It's now working as intended, with a little revision my app creates a horizontal chain as I Add and Place:
[View 00][View 01][View 02]
My android layout with grid view is not showing properly on 480 x 854 pixels (~196 ppi pixel density) device.and please suggest me is there any method to work with layout creation at run time.
Android categorizes device screens using two general properties: size
and density. You should expect that your app will be installed on
devices with screens that range in both size and density.
Create Different Layouts
To optimize your user experience on different screen sizes, you should create a unique layout XML file for each screen size you want to support. Each layout should be saved into the appropriate resources directory .
More info you can visit official guideline
Supporting Different Screen Sizes
#N.shah , For Gridview, You should make all view dynamic, So that all the cells come exactly on each and every device
How We can do this
Like we have 4 rows and 2 columns
All 4 rows should show on window
1. Find out the device width and height
2. Lets say height is X. Find out height of status bar i.e Y and action bar Z
3. Find out the exact height where we have to show our gridview i.e
X=X-(Y+Z)
4. Divide the X by no. of rows you want to show to find out row height i.e R
R=X/4( where 4 is no. of rows)
5. Create an xml which you want to show in gridview
custom_gridview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/ll_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_marginBottom="#dimen/menu_grid_vertical_spacing"
android:orientation="vertical"
android:weightSum="4.5" >
<View
android:id="#+id/view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.9"
android:gravity="center" >
<ImageView
android:id="#+id/img_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/app_name"
android:padding="#dimen/menu_page_padding"
android:src="#drawable/ic_launcher" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.4" />
<com.slinfy.ikharelimiteduk.custom.CustomTextViewSegoeUISemiBold
android:id="#+id/txt_name"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.2"
android:gravity="top|center_horizontal"
android:text="#string/app_name"
android:textColor="#android:color/white"
android:textSize="#dimen/app_menu_text_size" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="#dimen/menu_grid_vertical_spacing"
android:layout_alignParentBottom="true"
android:background="#2E3A60" />
</RelativeLayout>
Make an adapter
GridViewAdapter
import com.slinfy.ikharelimiteduk.R;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
#SuppressLint({ "ViewHolder", "InflateParams" })
public class GridViewAdapter extends BaseAdapter {
String[] mMenuNames;
int[] mColors;
Integer[] mMenuIcons;
Context mContext;
private LayoutInflater inflater;
float mGridSize;
float mPadding;
int noOfColums = 4;
public GridViewAdapter(String[] menuNames, Context context, int[] colors, Integer[] menuIcons, float gridSize) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mMenuNames = menuNames;
mMenuIcons = menuIcons;
mColors = colors;
mContext = context;
mGridSize = gridSize;
mPadding = context.getResources().getDimension(R.dimen.menu_grid_vertical_spacing);
}
#Override
public int getCount() {
return mMenuIcons.length;
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int arg0) {
return 0;
}
#Override
public View getView(int index, View arg1, ViewGroup arg2) {
ViewHolder holder = null;
if (arg1 == null) {
holder = new ViewHolder();
arg1 = inflater.inflate(R.layout.custom_gridview, null);
holder.imgMenu = (ImageView) arg1.findViewById(R.id.img_menu);
holder.txtName = (TextView) arg1.findViewById(R.id.txt_name);
holder.layout = (RelativeLayout) arg1.findViewById(R.id.layout);
arg1.setTag(holder);
} else {
holder = (ViewHolder) arg1.getTag();
}
holder.txtName.setText(mMenuNames[index]);
holder.imgMenu.setImageResource(mMenuIcons[index]);
holder.layout.setBackgroundResource(mColors[index]);
holder.layout.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT,
(int) ((mGridSize / noOfColums) - 5/* - (mPadding) - 6 */)));
return arg1;
}
class ViewHolder {
TextView txtName;
ImageView imgMenu;
RelativeLayout layout;
}
}
Set the adapter in your main class
GridView grid = (GridView) findViewById(R.id.grid_view);
grid.setAdapter(new GridViewAdapter(menuNames, getApplicationContext(), colors, menuIcons, gridSize));
I am currently working on rewriting one of my iOS apps to release on Android. I'm making good progress but I am looking for some guidance regarding the best way to approach the list rows.
These are the cells/rows I am trying to recreate:
As you can see, I have a white background view with padding around each edge and rounded corners, so I guess for this I would need to embed everything within a view of some sort? The other part I am unsure about is how to create the coloured circle on the right. Would this be another view with rounded corners and a coloured background? I haven't managed to figure out how to get this to the right of the two textViews that I currently have. So if anyone could give a code example then that would be great.
This is my current XML:
<ImageView
android:layout_width="78dp"
android:layout_height="78dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:scaleType="centerCrop"
android:adjustViewBounds="false"
android:id="#+id/attractionImageView"
android:contentDescription="Attraction Image"
android:background="#color/colorPrimary" />
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:background="#drawable/fast_pass"
android:id="#+id/fastPassImageView" />
<LinearLayout android:orientation="vertical" android:layout_height="match_parent" android:layout_width="fill_parent" android:layout_toEndOf="#+id/attractionImageView" android:layout_toRightOf="#+id/attractionImageView">
<TextView
android:layout_width="match_parent"
android:layout_height="49dp"
android:id="#+id/attractionNameTextView"
android:text="Attraction Name"
android:layout_marginLeft="5dp"/>
<LinearLayout android:orientation="horizontal" android:layout_height="match_parent" android:layout_width="fill_parent" android:layout_toEndOf="#+id/attractionImageView" android:layout_toRightOf="#+id/attractionImageView">
<ImageView
android:layout_width="13dp"
android:layout_height="13dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:id="#+id/updatedImageView"
android:background="#drawable/updated"
android:layout_gravity="center_vertical"/>
<TextView
android:layout_width="match_parent"
android:layout_height="29dp"
android:id="#+id/updatedTextView"
android:text="Updated"
android:gravity="center_vertical"/>
</LinearLayout>
</LinearLayout>
This seems to work well for everything I've got so far, but I'm not sure where to go from here. This is how it looks:
Any suggestions?
For the colored circle- I'd suggest just a text view set to the proper size with a circle drawable set as the background of the view. Should get what you want.
For the background- I'd just stick the entire row in either a linear or relative layout, then set a RoundedBitmapDrawable as the background of the layout. That will give you the rounded background effect. If necessary add some margin to the top and bottom of each view to increase the gap between items.
I suppose that you're using custom views for your listview's items, if so, I would set the background of the custom view to something like this:
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#color/white" />
<stroke android:width="4dp" android:color="#color/beige" /> //If you want a stroke
<corners
android:topLeftRadius="20dp"
android:topRightRadius="20dp"
android:bottomLeftRadius="20dp"
android:bottomRightRadius="20dp" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
As an alternate solution, I just got something working with CardViews and using Picasso with a CircleTransformation for the circle.
In this simple example, I used a RecyclerView of CardViews.
First, here is the CircleTransformation class that is used by Picasso:
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import com.squareup.picasso.Transformation;
public class CircleTransform implements Transformation {
#Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
paint.setShader(shader);
float r = size/2f;
canvas.drawCircle(r, r, r-1, paint);
Paint paintBorder = new Paint();
paintBorder.setStyle(Style.STROKE);
paintBorder.setColor(Color.argb(84,0,0,0));
paintBorder.setAntiAlias(true);
paintBorder.setStrokeWidth(1);
canvas.drawCircle(r, r, r-1, paintBorder);
squaredBitmap.recycle();
return bitmap;
}
#Override
public String key() {
return "circle";
}
}
Here is the Fragment:
public class BlankFragment extends Fragment {
public BlankFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_blank, container, false);
RecyclerView rv = (RecyclerView) rootView.findViewById(R.id.rv_recycler_view);
rv.setHasFixedSize(true);
MyAdapter adapter = new MyAdapter(new String[]{"testone", "testtwo", "testthree", "testfour"}, getActivity());
rv.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
return rootView;
}
}
fragment_blank.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
The adapter, which includes the defaultCircleWithText() method for drawing the circle and text. Here I'm just using one color for the circles, but you can extend this to set the correct circle color for each row:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDataset;
Context mContext;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public static class MyViewHolder extends RecyclerView.ViewHolder {
public CardView mCardView;
public TextView mTextView;
public ImageView mImageView;
public MyViewHolder(View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextView = (TextView) v.findViewById(R.id.tv_text);
mImageView = (ImageView) v.findViewById(R.id.iv_image);
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(String[] myDataset, Context context) {
mDataset = myDataset;
mContext = context;
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_item, parent, false);
// set the view's size, margins, paddings and layout parameters
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.mTextView.setText(mDataset[position]);
Drawable drawable = new BitmapDrawable(mContext.getResources(), defaultCircleWithText("test"));
Picasso.with(mContext).load((String)null).fit().transform(new CircleTransform()).placeholder(drawable).into(holder.mImageView);
}
#Override
public int getItemCount() {
return mDataset.length;
}
public final static int BIG_IMAGE = 138;
public static Bitmap defaultCircleWithText(String text) {
int size = BIG_IMAGE;
Bitmap image = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(image);
int alpha = 165;
//hard-coded circle color:
int color = Color.argb(alpha,253,70,45);
Paint p_circle = new Paint();
p_circle.setAntiAlias(true);
p_circle.setColor(color);
c.drawCircle(size/2f, size/2f, size/2f-1, p_circle);
Paint p_text = new Paint();
p_text.setAntiAlias(true);
p_text.setColor(Color.WHITE);
p_text.setTextSize(58);
RectF bounds = new RectF(0, 0, c.getWidth(), c.getHeight());
// measure text width
bounds.right = p_text.measureText(text, 0, text.length());
// measure text height
bounds.bottom = p_text.descent() - p_text.ascent();
bounds.left += (c.getWidth() - bounds.right) / 2.0f;
bounds.top += (c.getHeight() - bounds.bottom) / 2.0f;
c.drawText(text, bounds.left, bounds.top - p_text.ascent(), p_text);
return image;
}
}
card_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="78dp" >
<android.support.v7.widget.CardView
android:id="#+id/card_view"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
card_view:cardCornerRadius="4dp"
android:layout_width="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="test" >
</TextView>
<ImageView
android:id="#+id/iv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Result:
I got an Activity with two Fragments (one list one normal).
And the normal Fragment inflates a Scrollview containing a LineaLayout (vertical) and this layout contains TextViews.
The ScrollView and layout_width and layout_height are match_parent, so I think the whole screen should be used. But on the bottom there is still a "gap".
I hope you can help me.
ScrollView.xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/titlescreen_bg"
android:orientation="vertical"
android:paddingTop="60dp"
tools:context=".MainActivity" >
<TextView
android:id="#+id/tv_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="60dp"
android:paddingTop="60dp"
android:textIsSelectable="false"
android:textSize="#dimen/fontsize_slogan_titlescreen" />
<TextView
android:id="#+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:paddingBottom="30dp"
android:paddingTop="30dp"
android:textIsSelectable="false"
android:textSize="#dimen/fontsize_slogan_titlescreen" />
</LinearLayout>
</ScrollView>
the fragment inflating this layout.
package wak.iage.layout;
import wak.iage.R;
import android.app.Fragment;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MenuContentFragment extends Fragment
{
LinearLayout.LayoutParams relativeParams = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
LinearLayout topLayout = null;
TextView body = null;
TextView head = null;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.menu_content_main, container);
return v;
}
public void changeText(String title, String content) {
topLayout = (LinearLayout) getActivity().findViewById(
R.id.LinearLayout1);
head = (TextView) getActivity().findViewById(R.id.tv_headline);
body = (TextView) getActivity().findViewById(R.id.tv_content);
if (body == null) {
topLayout.removeViews(1, topLayout.getChildCount() - 1);
body = new TextView(getActivity().getApplicationContext());
body.setPadding(0, 30, 0, 20);
body.setTextColor(Color.BLACK);
body.setTextSize(22);
body.setGravity(Gravity.CENTER_HORIZONTAL);
topLayout.addView(body, relativeParams);
}
body.setText(content);
head.setText(title);
}
public void addGlossary() {
if (body != null) {
topLayout.removeView(body);
}
int i = 0;
for (int id : GLOSSARY) {
TextView glossary = new TextView(getActivity()
.getApplicationContext());
glossary.setText(getString(id));
glossary.setTextColor(Color.BLACK);
if (i % 2 == 0) {
glossary.setTypeface(Typeface.DEFAULT_BOLD);
glossary.setTextSize(22);
glossary.setPadding(0, 10, 0, 10);
}
topLayout.addView(glossary, relativeParams);
i += 1;
}
}
public static final int[] GLOSSARY = {
R.string.GlossaryAndroidOSTitle, R.string.GlossaryAndroidOSContent,
R.string.GlossaryAppTitle, R.string.GlossaryAppContent,
R.string.GlossaryCloudTitle, R.string.GlossaryCloudContent,
R.string.GlossaryDonwloadTitle, R.string.GlossaryDonwloadContent,
R.string.GlossaryFacebookTitle, R.string.GlossaryFacebookContent,
R.string.GlossaryGPSTitle, R.string.GlossaryGPSContent,
R.string.GlossaryHomescreenTitle,
R.string.GlossaryHomescreenContent, R.string.GlossaryPasswordTitle,
R.string.GlossaryPasswordContent, R.string.GlossaryRouterTitle,
R.string.GlossaryRouterContent, R.string.GlossarySDTitle,
R.string.GlossaySDContent, R.string.GlossayStandbyTitle,
R.string.GlossayStandbyContent, R.string.GlossaryTabletTitle,
R.string.GlossaryTabletContent, R.string.GlossaryTouchscreenTitle,
R.string.GlossaryTouchscreenContent, R.string.GlossayWidgetsTitle,
R.string.GlossayWidgetsContent, R.string.GlossayWLANTitle,
R.string.GlossayWLANContent };
}
Thanks a lot.
Edit: Even the proble is already fixed with: android:fillViewPort="true", I want to show you the problem.
But I don't have enough reputation to post a picture.
Sorry!
If i'm not mistaken, the ViewGroup's height (LinearLayout's height in your case), that is the (only) child inside a ScrollView, is always interpreted as wrap_content, since that content can be larger than the ScrollView's height (hence the scrollbars).
This also means that if the content is smaller, the ScrollView's content (child) may not necessarily stretch to fill the screen.
In order to visually help you fix this, we need to see a screenshot of your problem.
Maybe setting android:fillViewport="true" on the ScrollView will fix your issue:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:fadeScrollbars="false"
android:scrollbars="vertical" >
In your ScrollView add an attribute ie.
android:fillViewport="true"
inflater.inflate(R.layout.menu_content_main, container);
should be
inflater.inflate(R.layout.menu_content_main, container, false);
Replace ScrollView with NestedScrollView it will also solve the problem of nested scrolling.
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.core.widget.NestedScrollView>
I had a similar problem and could only fix it with a Helper Class. I found the original code online and this is my implementation of it.
Java class:
public class ImageViewHelper extends android.support.v7.widget.AppCompatImageView {
public ImageViewHelper(Context context) {
super(context);
}
public ImageViewHelper(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ImageViewHelper(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = w * d.getIntrinsicHeight() / d.getIntrinsicWidth();
setMeasuredDimension(w, h);
}
else super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
XML:
<com.example.app.ImageViewHelper
android:id="#+id/img"
android:src="#drawable/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:adjustViewBounds="true" />
I really want to implement this (the side navigation) in an app of my own, does anyone know how Google managed to do this?
They seem to have pulled the current window aside and put in a fly-in navigation of their own.
In fact, there's a way to do this. Even without implementing your own ActionBar.
Just have a look at the hierachyviewer! (Located in the tools directory)
There's the DecorView, and a LinearLayout as a child. This LinearLayout contains both the ActionBar and the other content. So, you can simply apply some FrameLayout.LayoutParams to this LinearLayout and get some space on the left side this way. Then, you can fill this space with your menu-ListView and overlay the other content with a FrameLayout, that, when it's clicked, collapses the menu. So, here's some code:
First, the class for collapsing / expanding (SlideMenu.java):
package your.cool.app;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
public class SlideMenu {
//just a simple adapter
public static class SlideMenuAdapter extends ArrayAdapter<SlideMenu.SlideMenuAdapter.MenuDesc> {
Activity act;
SlideMenu.SlideMenuAdapter.MenuDesc[] items;
class MenuItem {
public TextView label;
public ImageView icon;
}
static class MenuDesc {
public int icon;
public String label;
}
public SlideMenuAdapter(Activity act, SlideMenu.SlideMenuAdapter.MenuDesc[] items) {
super(act, R.id.menu_label, items);
this.act = act;
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
if (rowView == null) {
LayoutInflater inflater = act.getLayoutInflater();
rowView = inflater.inflate(R.layout.menu_listitem, null);
MenuItem viewHolder = new MenuItem();
viewHolder.label = (TextView) rowView.findViewById(R.id.menu_label);
viewHolder.icon = (ImageView) rowView.findViewById(R.id.menu_icon);
rowView.setTag(viewHolder);
}
MenuItem holder = (MenuItem) rowView.getTag();
String s = items[position].label;
holder.label.setText(s);
holder.icon.setImageResource(items[position].icon);
return rowView;
}
}
private static boolean menuShown = false;
private static View menu;
private static LinearLayout content;
private static FrameLayout parent;
private static int menuSize;
private static int statusHeight = 0;
private Activity act;
SlideMenu(Activity act) {
this.act = act;
}
//call this in your onCreate() for screen rotation
public void checkEnabled() {
if(menuShown)
this.show(false);
}
public void show() {
//get the height of the status bar
if(statusHeight == 0) {
Rect rectgle = new Rect();
Window window = act.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
statusHeight = rectgle.top;
}
this.show(true);
}
public void show(boolean animate) {
menuSize = Functions.dpToPx(250, act);
content = ((LinearLayout) act.findViewById(android.R.id.content).getParent());
FrameLayout.LayoutParams parm = (FrameLayout.LayoutParams) content.getLayoutParams();
parm.setMargins(menuSize, 0, -menuSize, 0);
content.setLayoutParams(parm);
//animation for smooth slide-out
TranslateAnimation ta = new TranslateAnimation(-menuSize, 0, 0, 0);
ta.setDuration(500);
if(animate)
content.startAnimation(ta);
parent = (FrameLayout) content.getParent();
LayoutInflater inflater = (LayoutInflater) act.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
menu = inflater.inflate(R.layout.menu, null);
FrameLayout.LayoutParams lays = new FrameLayout.LayoutParams(-1, -1, 3);
lays.setMargins(0,statusHeight, 0, 0);
menu.setLayoutParams(lays);
parent.addView(menu);
ListView list = (ListView) act.findViewById(R.id.menu_listview);
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//handle your menu-click
}
});
if(animate)
menu.startAnimation(ta);
menu.findViewById(R.id.overlay).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
SlideMenu.this.hide();
}
});
Functions.enableDisableViewGroup((LinearLayout) parent.findViewById(android.R.id.content).getParent(), false);
((ExtendedViewPager) act.findViewById(R.id.viewpager)).setPagingEnabled(false);
((ExtendedPagerTabStrip) act.findViewById(R.id.viewpager_tabs)).setNavEnabled(false);
menuShown = true;
this.fill();
}
public void fill() {
ListView list = (ListView) act.findViewById(R.id.menu_listview);
SlideMenuAdapter.MenuDesc[] items = new SlideMenuAdapter.MenuDesc[5];
//fill the menu-items here
SlideMenuAdapter adap = new SlideMenuAdapter(act, items);
list.setAdapter(adap);
}
public void hide() {
TranslateAnimation ta = new TranslateAnimation(0, -menuSize, 0, 0);
ta.setDuration(500);
menu.startAnimation(ta);
parent.removeView(menu);
TranslateAnimation tra = new TranslateAnimation(menuSize, 0, 0, 0);
tra.setDuration(500);
content.startAnimation(tra);
FrameLayout.LayoutParams parm = (FrameLayout.LayoutParams) content.getLayoutParams();
parm.setMargins(0, 0, 0, 0);
content.setLayoutParams(parm);
Functions.enableDisableViewGroup((LinearLayout) parent.findViewById(android.R.id.content).getParent(), true);
((ExtendedViewPager) act.findViewById(R.id.viewpager)).setPagingEnabled(true);
((ExtendedPagerTabStrip) act.findViewById(R.id.viewpager_tabs)).setNavEnabled(true);
menuShown = false;
}
}
Some helping methods (for me, in static Functions.java):
public static int dpToPx(int dp, Context ctx) {
Resources r = ctx.getResources();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
}
//originally: http://stackoverflow.com/questions/5418510/disable-the-touch-events-for-all-the-views
//modified for the needs here
public static void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if(view.isFocusable())
view.setEnabled(enabled);
if (view instanceof ViewGroup) {
enableDisableViewGroup((ViewGroup) view, enabled);
} else if (view instanceof ListView) {
if(view.isFocusable())
view.setEnabled(enabled);
ListView listView = (ListView) view;
int listChildCount = listView.getChildCount();
for (int j = 0; j < listChildCount; j++) {
if(view.isFocusable())
listView.getChildAt(j).setEnabled(false);
}
}
}
}
Then, the layouts:
Layout of the menu (res/layout/menu.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="250dip"
android:background="#color/darkblack">
<ListView
android:id="#+id/menu_listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="#color/dividerblack"
android:dividerHeight="2dip" />
</LinearLayout>
<FrameLayout
android:id="#+id/overlay"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
</LinearLayout>
Layout of the listitems (res/layout/menu_listitem.xml):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="fill_parent" >
<ImageView
android:id="#+id/menu_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="5dip"
android:layout_marginLeft="10dip"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip" />
<TextView
android:id="#+id/menu_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textSize="24dp"
android:layout_marginTop="10dip"
android:layout_marginBottom="10dip" />
</LinearLayout>
How to use it:
In your onCreate():
private SlideMenu slidemenu;
#Override
public void onCreate(Bundle savedInstanceState) {
//your onCreate code
slidemenu = new SlideMenu(this);
slidemenu.checkEnabled();
}
In the handler for your ActionBar homebutton:
slidemenu.show();
That's it!
And now, a little screenshot of it in action:
As far as I know, it is working. If you experience any problems or my explanations are not clear, please contact me!
EDIT: ExtendedViewPager & ExtendedPagerStrip:
ExtendedViewPager:
package your.cool.app;
//source: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class ExtendedViewPager extends ViewPager {
private boolean enabled;
public ExtendedViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
ExtendedPagerTabStrip:
package your.cool.app;
//source: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html
import android.content.Context;
import android.support.v4.view.PagerTabStrip;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class ExtendedPagerTabStrip extends PagerTabStrip {
private boolean enabled;
public ExtendedPagerTabStrip(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}
public void setNavEnabled(boolean enabled) {
this.enabled = enabled;
}
}
I use this SlideMenu for an Activity with a ViewPager with PagerTabStrip for tabs like Talk, Market etc. You can't disable these Views in an easy way, so the two classes above just extend them to stop the onTouch event when disabled.
There are several attempts at doing this, however I have yet to find a lib or source code on how to implement it successfully with actionbar accross all api levels. One promising lib is here
https://github.com/jfeinstein10/SlidingMenu
here is a video of the example app.
here is the Google Play app link.
This does work with ActionbarSherlock. You will have to build the SlidingMenu library with ABS to get it working. Works and looks great!
Did a roundup of the original implementation and added XML parsing as well as autodetection of a possibly present actionbar, so it works with the native as well as a support action bar such as ActionBarSherlock.
The whole thing is now a library project together with an example app and is described over at Sliding Menu for android Thanks to scirocco for the initial idea and code!
If you are using API level greater that 11 you can use a much simpler approach inspired by the answer given by #Scirocco
// get content parent that is basically the whole
// app screen (viewed from hierarchy viewer)
final LinearLayout content =
(LinearLayout) findViewById(android.R.id.content).getParent();
// make new value animator with range from 0 to 1
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
// set custom duration
animator.setDuration(500);
// on update is called for every value in the
// given range in time frame defined by the duration
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
// get the current value
float value = ((Float) (animation.getAnimatedValue())).floatValue();
// translate by that value, minus means translate left
content.setTranslationX(-250 * value);
}
});
// start the animator
animator.start();
// make or inflate custom view for test purposes
Button textView = new Button(this);
textView.setText("TestButton");
// add it to the frame layout that is the parent of the content on position 0
FrameLayout parent = (FrameLayout) content.getParent();
parent.addView(textView, 0);
The idea here is to use ValueAnimator that transforms and not just animates the main layout with the Action bar, so you can interact with the inflated view you want to use as a sliding panel.
You should replace the hardcoded values with something that is of use to your app.
I hope this helps :)
Well currently im working on a project and came across Sliding menu,i googled but gets very disappointed to see that no one has given some piece of code or some hint for how to start making a sliding menu,but every one has given link to some github's projects/libraries to use,I decided to do it myself and finally i have my own Sliding Menu Ready...
I have Spent two days on it
1. on making animations of sliding
2. on making it work with all screen resolutions
Its really easy and simple once you get some idea about Animations, i have read some where,its not sensible to re-invent the Wheel(people who are refering to github source code of sliding menu),but i beleif that you should atleast once try to make your own so you get a idea how it actually works and functions :P
so this is a picture of how my sliding menu will going to work
1.Find.xml //later in the code it will be refer as findLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="#+id/find_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="60dp"
android:padding="2dp"
android:background="#drawable/main_header">
<Button
android:id="#+id/filter"
android:layout_width="40dp"
android:layout_height="30dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:background="#drawable/filter_button" />
<TextView
android:id="#+id/city"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/filter"
android:layout_marginLeft="20dp"
android:layout_marginTop="3dp"
android:text="Islamabad"
android:textSize="22sp"
android:textStyle="bold"
android:textColor="#android:color/primary_text_dark"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/city"
android:layout_alignLeft="#+id/city">
<TextView
android:id="#+id/interested_in"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Men and Women"
android:textSize="12sp"
android:textColor="#android:color/primary_text_dark"/>
<ImageView
android:id="#+id/separator"
android:layout_width="2dp"
android:layout_height="18dp"
android:layout_toRightOf="#+id/interested_in"
android:layout_marginLeft="4dp"
android:src="#drawable/separator_1"
android:layout_centerVertical="true" />
<TextView
android:id="#+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_toRightOf="#+id/separator"
android:layout_centerVertical="true"
android:text="18-24 years"
android:textSize="12sp"
android:textColor="#android:color/primary_text_dark"/>
<ImageView
android:id="#+id/separator_1"
android:layout_width="2dp"
android:layout_height="18dp"
android:layout_toRightOf="#+id/age"
android:layout_marginLeft="4dp"
android:src="#drawable/separator_1"
android:layout_centerVertical="true" />
<TextView
android:id="#+id/distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_toRightOf="#+id/separator_1"
android:layout_centerVertical="true"
android:text=">30km"
android:textSize="12sp"
android:textColor="#android:color/primary_text_dark" />
</RelativeLayout>
</RelativeLayout>
<GridView
android:id="#+id/users_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/header"
android:numColumns="4">
</GridView>
</RelativeLayout>
<include
layout="#layout/filter"/> //here i included the filter.xml, which is on top of find.xml layout and is initially invisible
</RelativeLayout>
2.Filter.xml //later in code refer as FilterLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/filter_layout"
android:visibility="invisible"
android:layout_width="260dp"
android:layout_height="match_parent"
android:background="#drawable/grey_bg" >
<ImageView
android:id="#+id/profile_pic"
android:layout_width="match_parent"
android:layout_height="220dp"
android:src="#drawable/pic"/>
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="55dp"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:layout_below="#+id/profile_pic"
android:background="#drawable/light_blue_header">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:text="Raja Babar"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#android:color/primary_text_dark"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/name"
android:layout_alignLeft="#+id/name">
<TextView
android:id="#+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="Male"
android:textSize="12sp"
android:textColor="#android:color/primary_text_dark" />
<ImageView
android:id="#+id/seperator"
android:layout_width="2dp"
android:layout_height="20dp"
android:layout_toRightOf="#+id/gender"
android:layout_marginLeft="5dp"
android:src="#drawable/separator_1"
android:layout_centerVertical="true" />
<TextView
android:id="#+id/age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/seperator"
android:layout_marginLeft="5dp"
android:layout_centerVertical="true"
android:text="22 years"
android:textSize="12sp"
android:textColor="#android:color/primary_text_dark" />
</RelativeLayout>
</RelativeLayout>
<ScrollView
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="#+id/header"
android:layout_marginTop="15dp"
android:layout_centerHorizontal="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/filter_options"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/filter_options"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#android:color/primary_text_light"/>
<RelativeLayout
android:id="#+id/interested_in_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="40dp"
android:layout_below="#+id/filter_options"
android:background="#drawable/interested_in_field">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="#string/gender"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#android:color/primary_text_light"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="#string/women_men"
android:textSize="18sp"
android:textColor="#33b9cd" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/age_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="40dp"
android:layout_below="#+id/interested_in_layout"
android:background="#drawable/age_field_1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="#string/age"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#android:color/primary_text_light"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="18-24 years"
android:textSize="18sp"
android:textColor="#33b9cd"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingRight="40dp"
android:layout_below="#+id/age_layout"
android:background="#drawable/distance_field">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="#string/distance"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="#android:color/primary_text_light"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text=">30km"
android:textSize="18sp"
android:textColor="#33b9cd"/>
</RelativeLayout>
</RelativeLayout>
</ScrollView>
</RelativeLayout>
In find.xml i have included filter.xml initially which is invisible
Now FilterAnimation.java
package matchat.helpers;
import com.s3.matchat.R;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.RelativeLayout;
public class FilterAnimation implements AnimationListener
{
Context context;
RelativeLayout filterLayout, otherLayout;
private Animation filterSlideIn, filterSlideOut, otherSlideIn, otherSlideOut;
private static int otherLayoutWidth, otherLayoutHeight;
private boolean isOtherSlideOut = false;
private int deviceWidth;
private int margin;
public FilterAnimation(Context context)
{
this.context = context;
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
deviceWidth = displayMetrics.widthPixels; // as my animation is x-axis related so i gets the device width and will use that width,so that this sliding menu will work fine in all screen resolutions
}
public void initializeFilterAnimations(RelativeLayout filterLayout)
{
this.filterLayout = filterLayout;
filterSlideIn = AnimationUtils.loadAnimation(context, R.anim.filter_slide_in);
filterSlideOut = AnimationUtils.loadAnimation(context, R.anim.filter_slide_out);
}
public void initializeOtherAnimations(RelativeLayout otherLayout)
{
this.otherLayout = otherLayout;
otherLayoutWidth = otherLayout.getWidth();
otherLayoutHeight = otherLayout.getHeight();
otherSlideIn = AnimationUtils.loadAnimation(context, R.anim.other_slide_in);
otherSlideIn.setAnimationListener(this);
otherSlideOut = AnimationUtils.loadAnimation(context, R.anim.other_slide_out);
otherSlideOut.setAnimationListener(this);
}
public void toggleSliding()
{
if(isOtherSlideOut) //check if findLayout is already slided out so get so animate it back to initial position
{
filterLayout.startAnimation(filterSlideOut);
filterLayout.setVisibility(View.INVISIBLE);
otherLayout.startAnimation(otherSlideIn);
}
else //slide findLayout Out and filterLayout In
{
otherLayout.startAnimation(otherSlideOut);
filterLayout.setVisibility(View.VISIBLE);
filterLayout.startAnimation(filterSlideIn);
}
}
#Override
public void onAnimationEnd(Animation animation)
{
if(isOtherSlideOut) //Now here we will actually move our view to the new position,because animations just move the pixels not the view
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);
otherLayout.setLayoutParams(params);
isOtherSlideOut = false;
}
else
{
margin = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight);
params.leftMargin = margin;
params.rightMargin = -margin; //same margin from right side (negavite) so that our layout won't get shrink
otherLayout.setLayoutParams(params);
isOtherSlideOut = true;
dimOtherLayout();
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
}
#Override
public void onAnimationStart(Animation animation)
{
}
private void dimOtherLayout()
{
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);
alphaAnimation.setFillAfter(true);
otherLayout.startAnimation(alphaAnimation);
}
}
Now Find.java
package main.matchat.activities;
import matchat.helpers.FilterAnimation;
import com.s3.matchat.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.View.OnClickListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.Button;
import android.widget.RelativeLayout;
public class Find extends Activity implements OnClickListener
{
RelativeLayout filterLayout, findLayout;
Button btFilter;
FilterAnimation filterAnimation;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.find);
filterLayout = (RelativeLayout)findViewById(R.id.filter_layout);
findLayout = (RelativeLayout)findViewById(R.id.find_layout);
btFilter = (Button)findViewById(R.id.filter);
btFilter.setOnClickListener(this);
filterAnimation = new FilterAnimation(this);
initializeAnimations();
}
private void initializeAnimations()
{ //Setting GlobolLayoutListener,when layout is completely set this function will get called and we can have our layout onbject with correct width & height,else if you simply try to get width/height of your layout in onCreate it will return 0
final ViewTreeObserver filterObserver = filterLayout.getViewTreeObserver();
filterObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
filterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int deviceWidth = displayMetrics.widthPixels;
int filterLayoutWidth = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(filterLayoutWidth, RelativeLayout.LayoutParams.MATCH_PARENT);
filterLayout.setLayoutParams(params);//here im setting the layout params for my filter.xml because its has width 260 dp,so work it across all screen i first make layout adjustments so that it work across all screens resolution
filterAnimation.initializeFilterAnimations(filterLayout);
}
});
final ViewTreeObserver findObserver = findLayout.getViewTreeObserver();
findObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
findLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
filterAnimation.initializeOtherAnimations(findLayout);
}
});
}
#Override
public void onClick(View v)
{
int id = v.getId();
switch(id)
{
case R.id.filter:
filterAnimation.toggleSliding();
break;
}
}
}
Here are the animations res/anim
1.filter_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator">
<translate
android:fromXDelta="-100%"
android:toXDelta="0%"
android:duration="1000"
android:fillEnabled="true" />
</set>
2.filter_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator">
<translate
android:fromXDelta="0%"
android:toXDelta="-100%"
android:duration="1000"/>
</set>
3.other_slide_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator" >
<translate
android:fromXDelta="0%"
android:toXDelta="-80%"
android:duration="1000"
android:fillEnabled="true"/>
</set>
4.other_slide_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/decelerate_interpolator">
<translate
android:fromXDelta="0%"
android:toXDelta="80%"
android:duration="1000"
android:fillEnabled="true"/>
</set>
There you go a complete working and functional Sliding Menu, and you can customized it to meet your requirements,if any one still have some problems setting up,feel free to ask,i feel pleasure to help you out :)
I've created my own solution for sliding away the view and revealing a menu underneath, as many other solutions appeared to not work on older Android versions or lacked proper instructions on how to get it to work.
My solution has the following features:
Provides support for sliding away a view to reveal a menu that lies underneath it
Both the menu and the view above can be any custom View
Supported on old Android versions (tested to work at least on Android 2.2)
Works with PhoneGap / Cordova projects
The solution uses a custom layout, called SlidingMenuLayout, that you are expected to add 2 views to. The first view you add is the menu, the second is the main view.
The simplest way to add the layout to your existing project is to override your Activity's setContentView() method:
#Override
public void setContentView(View view) {
SlidingMenuLayout layout = new SlidingMenuLayout(this);
layout.setLayoutParams(new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
0.0F));
layout.addView(new MenuView(this));
layout.addView(view);
super.setContentView(layout);
}
In this example, MenuView is the view that will actually show the menu. It is up to you to implement this view.
Finally, you can add a button (typically in the top left corner of your main view), that calls openMenu() or closeMenu() on the layout as appropriate.
The code for SlidingMenuLayout is found on the GitHub project page.
For those of you who uses the SlidingMenu library (https://github.com/jfeinstein10/SlidingMenu) there is a way to jack it in and it seems to work! With help of #Scirocco put this in your onCreate for the activity:
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
mSlidingMenu = new SlidingMenu(this);
ViewGroup mainContent = (ViewGroup) decorView.getChildAt(0);
decorView.removeView(mainContent);
mSlidingMenu.setContent(mainContent);
decorView.addView(mSlidingMenu);
mMenu = (LinearLayout) View.inflate(this, R.layout.menuview, null);
mSlidingMenu.setMenu(mMenu);
mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
basically what it does is replacing the linearlayout in decor view with the slidingmenu instead.
Notice: Ive only tested it lightly but it seems to work.
public class ImprovedSlidingPaneLayout extends SlidingPaneLayout {
Context context;
FrameLayout left;
FrameLayout right;
Boolean canOpen = true;
public ImprovedSlidingPaneLayout(Context context) {
super(context);
this.context = context;
this.left = new FrameLayout(context);
this.right = new FrameLayout(context);
this.addView(left);
this.addView(right);
}
public ImprovedSlidingPaneLayout(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (canOpen)
return super.onInterceptTouchEvent(ev);
else
return false;
}
public ImprovedSlidingPaneLayout canOpen(Boolean canOpen) {
this.canOpen = canOpen;
return this;
}
public ImprovedSlidingPaneLayout makeActionBarSlide(Window window){
ViewGroup decorView = (ViewGroup) window.getDecorView();
ViewGroup mainContent = (ViewGroup) decorView.getChildAt(0);
decorView.removeView(mainContent);
setContentView(mainContent);
decorView.addView(this);
return this;
}
public ImprovedSlidingPaneLayout setMenuView(View view){
if((left.getChildCount()== 1)){
left.removeView(left.getChildAt(0));
}
left.addView(view);
return this;
}
public ImprovedSlidingPaneLayout setContentView(View view){
if((right.getChildCount()== 1)){
right.removeView(right.getChildAt(0));
}
right.addView(view);
return this;
}
public ImprovedSlidingPaneLayout setMenuWidth(int width){
left.setLayoutParams(new SlidingPaneLayout.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT));
return this;
}
}
this is my class extends SlidingPaneLayout. Can slide with actio