Changing font in Listview without using extra adapter class - java

I am not able to change the fonts of rows in a listview. I am not using extra adapter class and rows are populated statically. I am wondering how can I change fonts of rows. Below you can find my code for that.
public class Program extends Activity {
private String[] gunler =
{"Studio 1", "Studio 2", "Spinning", "Cross Fit"};
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
setContentView(R.layout.activity_program);
//(A) adımı
ListView listemiz=(ListView) findViewById(R.id.listView1);
//(B) adımı
ArrayAdapter<String> veriAdaptoru=new ArrayAdapter<String>
(this, android.R.layout.simple_list_item_1, android.R.id.text1, gunler);
final Typeface font = Typeface.createFromAsset(getAssets(),
"futura-condensed-medium.ttf");
//(C) adımı
listemiz.setAdapter(veriAdaptoru);
listemiz.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Intent intent = new Intent(Program.this, ProgramDetail.class);
int keyIdentifer = -1;
intent.putExtra("kacinciGun", new Integer(position+1).toString());
startActivity(intent);
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
return super.onOptionsItemSelected(item);
}
}
and layout file:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</RelativeLayout>

You can do this using a custom TextView where you set the font there.
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "your font name here");
setTypeface(typeface);
}
}
Then create a new layout using this new textview
<com.your.package.CustomTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
Then in your activity create the adapter like so
ArrayAdapter<String> veriAdaptoru = new ArrayAdapter<String>
(this, R.layout.some_layout, R.id.text, gunler);

Related

RecyclerView Android Dynamic Height

I am looking at creating dynamic heights in my RecyclerView to be responsive across all devices. Currently this works fine but for the first two rows at the start I have a double cell and the height of these two rows gets set to the first cell. I want instead this cell on both the first and second row to match the height of the last cell and become a rectangle. I have tried a few ways but none seem to work I am not sure where the problem is but I hope someone can show me. I will attach screenshots and the code below.
SquareLayout.java
public class SquareLayout extends LinearLayout {
public SquareLayout(Context context) {
super(context);
}
public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int width, int height) {
// int width = MeasureSpec.getSize(widthMeasureSpec);
//int height = MeasureSpec.getSize(heightMeasureSpec);
// note we are applying the width value as the height
//if(width>=370){
// super.onMeasure(widthMeasureSpec, widthMeasureSpec/2);
// }
// else{
// super.onMeasure(widthMeasureSpec, widthMeasureSpec);
// }
super.onMeasure(width, width);
// Log.d("int","int is: "+ width);
}
}
DataAdapter.java
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<AndroidVersion> android;
private Context context;
public DataAdapter(Context context,ArrayList<AndroidVersion> android) {
this.android = android;
this.context = context;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
// int width = viewHolder.tv_android.getMeasuredWidth() / 2; //returns -1
Log.d("MYINT", "value: " + i);
//Picasso.with(context).load(android.get(i).getAndroid_image_url()).resize(240, 120).into(viewHolder.img_android);
}
#Override
public int getItemCount() {
return android.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private LinearLayout testheight;
private ImageView img_android;
public ViewHolder(View view) {
super(view);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private final String android_version_names[] = {
"test1",
"test2",
"test3",
"test4",
"test5",
"test6",
"test7",
"test8",
"test9",
"test10"
};
private final String android_image_urls[] = {
"http://example.com/images/test.png",
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(),3);
ArrayList<AndroidVersion> androidVersions = prepareData();
((GridLayoutManager) mLayoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (position == 0 || position == 2) {
return 2; // ITEMS AT POSITION 1 AND 6 OCCUPY 3 SPACES
}
else {
return 1; // OTHER ITEMS OCCUPY ONLY A SINGLE SPACE
}
}
});
recyclerView.setLayoutManager(mLayoutManager);
DataAdapter adapter = new DataAdapter(getApplicationContext(), androidVersions);
recyclerView.setAdapter(adapter);
}
private ArrayList<AndroidVersion> prepareData(){
ArrayList<AndroidVersion> android_version = new ArrayList<>();
for(int i=0;i<android_version_names.length;i++){
AndroidVersion androidVersion = new AndroidVersion();
androidVersion.setAndroid_version_name(android_version_names[i]);
androidVersion.setAndroid_image_url(android_image_urls[i]);
android_version.add(androidVersion);
}
return android_version;
}
}
row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<example.SquareLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="10dp"
android:background="#color/reloadedpurple"
android:elevation="6dp"
android:orientation="vertical">
<ImageView
android:id="#+id/img_android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<TextView
android:id="#+id/tv_android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:textColor="#FFFFFF"
android:textStyle="bold" />
</LinearLayout>
</example.SquareLayout>

Custom ImageView class onClick change imageResource

I've created a custom ImageView class, and I'm trying to change the imageResource when user click on it, but I'm able to call setImageResource() from that class.
Also I'd like to store like a second imageView I mean, my custom ImageView has the same starter imageView resource, but when click on it it have to be dynamic ImageView for instance:
ImageView1 ic_launcher (user has not clicked on it)
ImageView1 ic_user (user has clicked on it)
Can you guide how to achieve this?
This is my custom ImageView class :
public class CustomImageView extends android.support.v7.widget.AppCompatImageView implements View.OnClickListener {
private View.OnClickListener clickListener;
public CustomImageView(Context context) {
super(context);
setOnClickListener(this);
}
public CustomImageView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
setOnClickListener(this);
}
public CustomImageView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOnClickListener(this);
}
#Override
public void setOnClickListener(OnClickListener l) {
if (l == this) {
super.setOnClickListener(l);
} else {
clickListener = l;
}
}
#Override
public void onClick(View v) {
//Should change the imageResource here but also I should have to change it again if user wants (to the initial one)
if (clickListener != null) {
clickListener.onClick(this);
}
}
}
A solution for a custom toggleable ImageView:
Custom attribute in values/attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ToggleImageView">
<attr name="low_img" format="reference" />
<attr name="high_img" format="reference" />
</declare-styleable>
</resources>
Custom ImageView class:
public class ToggleImageView extends AppCompatImageView implements View.OnClickListener {
private Drawable mLowDrawable, mHighDrawable;
private boolean isLow = true;
public ToggleImageView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
// Extract drawables from custom attributes
TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.ToggleImageView);
setLowDrawable(values.getDrawable(R.styleable.ToggleImageView_low_img));
setHighDrawable(values.getDrawable(R.styleable.ToggleImageView_high_img));
values.recycle();
setImageDrawable(mLowDrawable);
super.setOnClickListener(this);
}
public void setLowDrawable(Drawable drawable) {
mLowDrawable = drawable;
if (isLow)
setImageDrawable(mLowDrawable);
}
public void setHighDrawable(Drawable drawable) {
mHighDrawable = drawable;
if (!isLow)
setImageDrawable(mHighDrawable);
}
#Override
public void setOnClickListener(#Nullable OnClickListener l) {
// Do nothing to block setting listener from outer caller
}
#Override
public void onClick(View view) {
toggle();
}
public void toggle() {
isLow = !isLow;
setImageDrawable(isLow ? mLowDrawable : mHighDrawable);
}
}
Usage in xml layout:
<?xml version="1.0" encoding="utf-8" ?>
<FrameLayout 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:id="#+id/root_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.tamhuynh.testfragment.ToggleImageView
android:id="#+id/toggle_img"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
app:high_img="#mipmap/high_drawable"
app:low_img="#drawable/low_drawable"
tools:low_img="#drawable/low_drawable" />
</FrameLayout>

Why is the onDraw Not Being Called in Custom View for Android?

I am developing in Android Canvas.
But the onDraw() has not called after invalidate();
In the layout.xml
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.wen.MainActivity">
<com.wen.Drawpath_view
android:id="#+id/view_path"
android:layout_weight="0.7"
android:layout_width="match_parent"
android:layout_height="0dp"/>
<RelativeLayout
android:layout_weight="0.3"
android:layout_width="match_parent"
android:layout_height="0dp">
<Button
android:id="#+id/test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
In the MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private Drawpath_view View_path;
private Button test_btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View_path = findViewById(R.id.view_path);
View_path = new Drawpath_view(MainActivity.this);
test_btn = findViewById(R.id.test);
test_btn.setOnClickListener(this);
View_path.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
View_path.getViewTreeObserver().removeOnPreDrawListener(this);
View_path.setMinimumHeight(View_path.getHeight());
View_path.setMinimumWidth(View_path.getWidth());
return true;
}
});
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.test){
View_path.Testdraw();
}
}
}
In the customer View.
public class Drawpath_view extends View {
private static final String TAG = "view";
private Paint paint;
private Path path = new Path();
public Drawpath_view(Context context) {
super(context);
setWillNotDraw(false);
initView();
}
public Drawpath_view(Context context, AttributeSet attrs) {
super(context, attrs);
}
private void initView() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(3);
}
public void Testdraw(){
Log.d(TAG,"draw");
path.moveTo(60,60);
path.lineTo(460,460);
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Log.d(TAG,"onDraw");
super.onDraw(canvas);
canvas.drawPath(path,paint);
}
}
When I click the button in Activity. It will call
View_path.Testdraw();
But the onDraw in Drawpath_view has not been called. Did I missing something ?
Thanks in advance.
You can remove View_path = new Drawpath_view(MainActivity.this); from your code,
as you already attached view in xml.
By default all ViewGroup sub-classes do not call their onDraw method, you will enable it by calling setWillNotDraw(false) on View_path.
Add setWillNotDraw(false); initView();
into the second constructor as well.

Add Navigation Drawer to an existing activity

I have an app I am writing and it is already contains a lot of code, I decided I want to add a navigation drawer to the main activity toolbar but I don't know how to do it without creating a new navigation drawer project and copy my whole project to it which seems like a lot of work, is there a tutorial to add a navigation drawer to an existing project?
Create a layout layout_left_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bgLeftMenu">
<ImageView android:id="#+id/header"
android:src="#drawable/ic_launcher"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="26dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="30dp"
android:layout_marginStart="40dp"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginTop="26dp"
android:layout_marginLeft="10dp"
android:layout_toRightOf="#id/header">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true">
<TextView
android:id="#+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textColor="#color/pressed"/>
<TextView
android:id="#+id/userEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:layout_below="#id/userName"
android:layout_centerInParent="true"
android:textColor="#color/pressed"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
<ListView android:id="#+id/menu_items_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/header"
android:dividerHeight="0dp"
android:divider="#null"
android:background="#color/bgLeftMenu"/>
<ProgressBar android:id="#+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout>
Inflate it in a Custom View:
public class SimpleLeftMenuView extends NavigationView {
private LayoutInflater mInflater;
private Context mContext;
private ListView mItemsList;
private MenuItemsAdapter mItemsAdapter;
private ProgressBar mProgress;
private OnClickMenu mListener;
private ImageView mHeader;
private TextView userName;
private TextView userEmail;
//region Constructors
public SimpleLeftMenuView(Context context) {
super(context);
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
initLayout();
setData();
}
public SimpleLeftMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
initLayout();
setData();
}
public SimpleLeftMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
initLayout();
setData();
}
//endregion
private void initLayout(){
mInflater.inflate(R.layout.layout_left_menu, this);
mItemsList = (ListView) findViewById(R.id.menu_items_list);
mProgress = (ProgressBar) findViewById(R.id.progress);
mHeader = (ImageView) findViewById(R.id.header);
userName = (TextView) findViewById(R.id.userName);
userEmail = (TextView) findViewById(R.id.userEmail);
mHeader.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// do something
}
});
}
public void setSelectedSection(String idSection) {
mItemsAdapter.setLastSelectedSection(idSection);
}
public void setmListener(OnClickMenu mListener) {
this.mListener = mListener;
}
private void setData() {
List<String> sections = new ArrayList<>();
sections.add(mContext.getString(R.string.home_id));
sections.add(mContext.getString(R.string.login_id));
sections.add(mContext.getString(R.string.settings_id));
//.........
//sections.add(mContext.getString(R.string.exit_id));
mItemsAdapter = new MenuItemsAdapter(mContext, sections, new OnClickMenu() {
#Override
public void onClick(String id) {
mItemsAdapter.setLastSelectedSection(id);
if (mListener != null)
mListener.onClick(id);
}
});
mItemsList.setAdapter(mItemsAdapter);
mItemsList.setSelection(0);
mItemsList.setItemChecked(0, true);
}
}
You have to create the MenuItemAdapter.
public class MenuItemsAdapter extends BaseAdapter {
private Context mContext;
private static String lastSelectedSection;
private List<String> mSections;
private int currentTextcolor;
private OnClickMenu mListener;
public MenuItemsAdapter(Context context, List<String> sections, OnClickMenu listener) {
mContext = context;
mSections = sections;
mListener = listener;
lastSelectedSection = sections.get(0);
}
#Override
public int getCount() {
return mSections.size();
}
#Override
public String getItem(int position) {
return mSections.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView, ViewGroup parent) {
final MenuItemHolder holder;
if (convertView==null){
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.layout_left_menu_item, parent, false);
holder = new MenuItemHolder(convertView);
convertView.setTag(holder);
}else {
holder = (MenuItemHolder) convertView.getTag();
}
Resources r = mContext.getResources();
int pxMarginSection = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, r.getDisplayMetrics());
holder.position = position;
holder.mLine.setVisibility(View.GONE);
holder.mTitle.setTextColor(mContext.getResources().getColor(R.color.primary));
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
if (mSections.get(position).equals(mContext.getString(R.string.login_id))) {
holder.mIconView.setImageResource(R.drawable.ic_login_gp);
// holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
holder.mTitle.setText(mContext.getString(R.string.action_login));
holder.mLine.setVisibility(View.VISIBLE);
holder.mLayoutItem.setPadding(0, pxMarginSection, 0, pxMarginSection);
} else if (mSections.get(position).equals(mContext.getString(R.string.settings_id))) {
holder.mIconView.setImageResource(R.drawable.option);
holder.mTitle.setText(mContext.getString(R.string.action_settings));
holder.mLayoutItem.setPadding(0, pxMarginSection, 0, pxMarginSection);
holder.mLine.setVisibility(View.VISIBLE);
} else if (mSections.get(position).equals(mContext.getString(R.string.exit_id))) {
holder.mIconView.setImageResource(R.drawable.shutdown);
holder.mTitle.setText(mContext.getString(R.string.salir));
holder.mLayoutItem.setPadding(0, pxMarginSection, 0, pxMarginSection);
holder.mLine.setVisibility(View.VISIBLE);
}
holder.mLayoutItem.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getActionMasked()){
case MotionEvent.ACTION_DOWN:
currentTextcolor = holder.mTitle.getCurrentTextColor();
holder.mLayoutItemSelect.setBackgroundColor(mContext.getResources().getColor(R.color.primary));
holder.mTitle.setTextColor(mContext.getResources().getColor(R.color.text_info));
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.text_info));
return true;
case MotionEvent.ACTION_UP:
holder.mLayoutItemSelect.setBackgroundResource(R.color.bgLeftMenu);
holder.mTitle.setTextColor(currentTextcolor);
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
mListener.onClick(mSections.get(position));
return true;
case MotionEvent.ACTION_CANCEL:
holder.mLayoutItemSelect.setBackgroundColor(mContext.getResources().getColor(R.color.bgLeftMenu));
holder.mTitle.setTextColor(currentTextcolor);
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
return true;
}
return false;
}
});
return convertView;
}
class MenuItemHolder {
// butterKnife
View view;
#Bind(R.id.title)
TextView mTitle;
#Bind(R.id.icon)
ImageView mIconView;
#Bind(R.id.layoutItem)
LinearLayout mLayoutItem;
#Bind (R.id.rl_line)
View mLine;
#Bind(R.id.layoutItemSelect)
LinearLayout mLayoutItemSelect;
int position;
public MenuItemHolder(View itemView) {
ButterKnife.bind(this, itemView);
view = itemView;
}
}
public void setLastSelectedSection(String idSection) {
lastSelectedSection = idSection;
}
}
Now you have to modify your current Activity:
Change your main activity layout to use DrawerLayout and add your custom view "SimpleLeftMenuView":
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#EDEDED">
// YOUR CURRENT LAYOUT
<yourpackage.custom.SimpleLeftMenuView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/bgLeftMenu"/>
</android.support.v4.widget.DrawerLayout>
Activity class:
Add global variables:
protected #Bind(R.id.navigation_view) SimpleLeftMenuView mLeftMenuView;
protected #Bind(R.id.drawerLayout) DrawerLayout mDrawerLayout;
Set onclick listener. You can do an actions depends on the id:
mLeftMenuView.setmListener(new OnClickMenu() {
#Override
public void onClick(String id) {
Log.d("MENU", "ic_menu_hamburger clicked: " + id);
closeDrawer(null);
if (id.equals(getString(R.string.settings_id))) {
Intent intent = new Intent(MainActivity.this,
SettingsActivity.class);
MainActivity.this.startActivity(intent);
} else if (id.equals(getString(R.string.exit_id))) {
// salir
showRateDialogBeforeExit();
}
}
});
I have created my own interface OnClickMenu:
public interface OnClickMenu {
void onClick(String id);
}
And add action to open drawer from menu icon:
#Override
public void onBackPressed() {
if((mDrawerLayout) != null && (mDrawerLayout.isDrawerOpen(GravityCompat.START)))
closeDrawer(null);
else {
super.onBackPressed();
}
}
public void closeDrawer(DrawerLayout.DrawerListener listener) {
mDrawerLayout.setDrawerListener(listener);
mDrawerLayout.closeDrawers();
}
public void openDrawer() {
mDrawerLayout.setDrawerListener(null);
mDrawerLayout.openDrawer(GravityCompat.START);
}
Menu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_home, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
openDrawer();
return true;
}
return super.onOptionsItemSelected(item);
}
add to app build.gradle
compile 'com.android.support:design:26.0.0'
compile 'com.jakewharton:butterknife:8.6.0'
Change all #Bind to #BindView
The easiest way for you would be using this library.
Its really easy to implement and its very flexible.
If you want to do it yourself, consider reading official docs about creating navigation drawer.
I've tried the MaterialDrawer library, as suggested by #yury-dombaev and I have to admit it's far easier to implement than the official Navigation Drawer.
It's possible to implement either with Android X dependencies or with the normal ones.
In my case, since I have the normal ones, I've to stick with the MaterialDrawer 6.0.9v. Although there's a migration guide that I'll give a look.
To implement the library within your current activity do the following:
Add the dependencies in your app build.gradle as explained in Setup 1 of the v 6.0.9 of the library: https://github.com/mikepenz/MaterialDrawer/tree/v6.0.9
Add your drawer in the onCreate() method of your Activity: new DrawerBuilder().withActivity(this).build();.
Now you've got a basic (and useless) lateral menu. So it's time you continue reading the Material Drawer documentation and add menu elements :)

GridView row not inflating

I have a simple GridView with custom Adapter in my layouts. My code is as follows:
CircleActivity.java:
public class CircleActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_circle);
List<Integer> listColors = new ArrayList<>();
listColors.add(getResources().getColor(R.color.colorAccent));
listColors.add(getResources().getColor(R.color.colorPrimary));
listColors.add(getResources().getColor(R.color.colorPrimaryDark));
GridView gridView = (GridView) findViewById(R.id.grid_colors);
CircleAdapter adapter = new CircleAdapter(this,listColors);
gridView.setAdapter(adapter);
}
}
activity_circle.xml:
<?xml version="1.0" encoding="utf-8"?>
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_colors"
android:layout_width="match_parent"
android:layout_height="match_parent" />
CircleAdapter.java:
public class CircleAdapter extends BaseAdapter{
private Context context;
private List<Integer> listColor;
public CircleAdapter(Context context, List<Integer> listColor) {
this.listColor = listColor;
this.context = context;
}
#Override
public int getCount() {
return listColor.size();
}
#Override
public Integer getItem(int position) {
return listColor.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_grid,parent,false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.customCircleView.setFillColor(listColor.get(position));
holder.customCircleView.setCircleRadius(100);
return convertView;
}
static class ViewHolder{
private CustomCircleView customCircleView;
public ViewHolder(View row){
customCircleView = (CustomCircleView) row.findViewById(R.id.custom_circle_view);
}
}
}
row_grid.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="#color/colorAccent"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent">
<com.droidexperiments.gridexpand.CustomCircleView
android:id="#+id/custom_circle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:fill_color="#color/colorPrimary"
custom:circle_radius="50"
android:padding="25dp" />
</LinearLayout>
CircleView.java:
public class CustomCircleView extends View {
private int circleRadius = 20;
private int fillColor = Color.BLACK;
public CustomCircleView(Context context) {
super(context);
}
public CustomCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomCircleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomCircle);
circleRadius = typedArray.getInteger(R.styleable.CustomCircle_circle_radius,20);
fillColor = typedArray.getColor(R.styleable.CustomCircle_fill_color, Color.BLACK);
typedArray.recycle();
}
public int getCircleRadius() {
return circleRadius;
}
public void setCircleRadius(int circleRadius) {
this.circleRadius = circleRadius;
}
public int getFillColor() {
return fillColor;
}
public void setFillColor(int fillColor) {
this.fillColor = fillColor;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(fillColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(canvas.getWidth()/2,canvas.getHeight()/2,circleRadius,paint);
}
}
attrts.xml:
<declare-styleable name="CustomCircle">
<attr name="fill_color" format="reference|color"/>
<attr name="circle_radius" format="integer"/>
</declare-styleable>
The issue is that screen remains blank and no row is inflated/showing in GridView.
I have checked everything. There is not any issue in GridView or the layout of grid row or in CustomCircleView. If I change adapter to simple ArrayAdapter, it works fine. So, there must be issue with my adapter:
I double checked getView() in adapter;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.row_grid,parent,false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
holder.customCircleView.setFillColor(listColor.get(position));
holder.customCircleView.setCircleRadius(100);
return convertView;
}
but couldn't identify why it shows blank. can anyone help me please?
When you implement a custom view, it is essential that you implement onMeasure. This method will tell the Android framework what size your view should be. Since you didn't specify this for CustomCircleView and used wrap_content in your layout, it had size zero. Therefore, all the elements of the GridView were invisible, making it look like the adapter was not working. I made a simple example implementation of onMeasure that solves your problem (just add this method in CustomCircleView):
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int size = View.MeasureSpec.makeMeasureSpec(2 * this.circleRadius, MeasureSpec.EXACTLY);
setMeasuredDimension(size, size);
}
The documentation advises that size stays within the given parameters (widthMeasureSpec and heightMeasureSpec). I have not included that restriction here, you can determine yourself what you want to do in that case.
You can find more information about this in the guide on creating custom components. Specific information about onMeasure can be found here.

Categories