I have an xml file and I want to change it to a component by using a class which extends View.
how Can I do that ??
java code :
public class custom extends View {
public custom(Context context) {
super(context);
}
public custom(Context context , AttributeSet attrs) {
super(context , attrs);
}
}
and this is my xml code :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.apd.ecryptfolders.custom">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"/>
Thanks!
You have to create a class that extends layout root view and then inflate the xml layout
public class CustomView extends RelativeLayout {
public CustomView(Context context) {
super(context);
View view = inflate(getContext(), R.layout.layout_name, null);
addView(view);
// init layout
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
View view = inflate(getContext(), R.layout.layout_name, null);
addView(view);
// here you can apply custom attributes
// init layout
}
}
These links can help you:
https://developer.android.com/training/custom-views/create-view
https://developer.android.com/guide/topics/ui/custom-components
Related
I have a TextView at the bottom of the CoordinatorLayout.
But when I show a SnackBar , it will cover the TextView.
I know I have to customize a Behavior for the TextView and override layoutDependsOn and onDependentViewChanged,but it doesn't fix very well.
Could you give me some advice if you know? Thanks.
If the TextView is a direct child of a CoordinatorLayout, just add
app:layout_dodgeInsetEdges="bottom"
in the TextView attributes.
Magic!
You need to add a behavior to your LinearLayout and embed it in a CoordinatorLayout.
Here is how you do that.
MoveUpwardBehavior.class
import android.os.Build;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.view.View;
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> {
private static final boolean SNACKBAR_BEHAVIOR_ENABLED;
#Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout;
}
#Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
child.setTranslationY(translationY);
return true;
}
static {
SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11;
}
}
CustomLinearLayout.class
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.widget.LinearLayout;
#CoordinatorLayout.DefaultBehavior(MoveUpwardBehavior.class)
public class CustomLinearLayout extends LinearLayout {
public CustomLinearLayout(Context context) {
super(context);
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
Sample xml->activity_home
Here user.example.charu.its2017huree is my package name replace it with yours!
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">
<user.example.charu.its2017huree.CustomLinearLayout
android:background="#098"
android:gravity="bottom"
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello world" />
</user.example.charu.its2017huree.CustomLinearLayout>
Finally in my Activity called HomeActivity
public class HomeActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
CustomLinearLayout customLinearLayout = (CustomLinearLayout) findViewById(R.id.linearLayout);
Snackbar.make(customLinearLayout, "Text to display", Snackbar.LENGTH_LONG).show();
}
}
Source is from this example.
I know it may seem a little dumb!
correct me if I'm thinking wrong.
I made a custom relativeLayout which has some sort of a dynamic behavior depended on screen size. and I need to add an imageView inside this layout which inherits its dimensions just like its parent.
I want to know if there's a way that I can implement an imageview within my custom layout class so that everytime I add it in a layout, the imageview comes along in it?
Of course you can add any View you want automatically within the custom RelativeLayout. I see a few different approaches you could take.
1- Create an xml layout for the content of your custom RelativeLayout, you could also use a <merge> as root tag if you have many views:
public class CustomRelativeLayout extends RelativeLayout {
private ImageView imageView;
public CustomRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
inflate(context, R.layout.custom_relative_layout, this);
imageView = (ImageView) findViewById(R.id.image_view);
}
}
custom_relative_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/image_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
2- create the View programmatically
public class CustomRelativeLayout extends RelativeLayout {
private ImageView imageView;
public CustomRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
imageView = new ImageView(context);
LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imageView.setLayoutParams(layoutParams);
addView(imageView);
}
}
3- create an xml with your CustomRelativeLayout and any child View in it, than include it in other layouts with <include>. Get a reference of the children Views in onFinishInflate()
public class CustomRelativeLayout extends RelativeLayout {
ImageView imageView;
#Override
protected void onFinishInflate() {
super.onFinishInflate();
imageView = (ImageView) findViewById(R.id.image_view);
}
}
custom_relative_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.CustomRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</com.example.CustomRelativeLayout>
and use it somewhere else with
<include layout="#layout/custom_relative_layout"/>
I am in need of a custom toolbar for a new app that I am writing. When I try to add the view to my main layout it doesn't align properly. Can someone please explain why?
public class LjCustomToolbar extends Toolbar {
private Context context;
private LayoutInflater layoutInflater;
private TextView toolbar_title;
public LjCustomToolbar(Context context) {
super(context);
initialize(context);
}
public LjCustomToolbar(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
public LjCustomToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initialize(context);
}
private void initialize(Context context) {
this.context = context;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.custom_toolbar, this);
}
}
custom_toolbar.xml
<Toolbar
style="#style/LjToolBarDefault"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Profile"
style="#style/LjBodyNormalText"
android:textColor="#color/white"
android:layout_gravity="center"
android:id="#+id/toolbar_title_text" />
</Toolbar>
activity_main.xml
<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"
android:gravity="center_horizontal"
android:background="#color/lj_color_primary">
<us.lj.CustomViews.LjCustomToolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
Click here to see my current layout
Can you show a screenshot, to see what is not working.
Why do you want to customize the Toolbar? If you want to add another views inside the toolbar you can do it in xml as all other UI elements
I am new in world of android developement and I want to make a clock such that each digit of time has it's own typeface.
Hour digits has it's own typeface and minutes digit has its own typeface.
How can i do this. Help me.
Let's say your font name is DemoFont . Make a Class which extends TextView. And initialize the font for the DemoFont .
Next place the .ttf file of that font in the assets folder.
public class DemoFont extends TextView {
public DemoFont (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public DemoFont (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DemoFont (Context context) {
super(context);
init();
}
private void init() {
Typeface tf = Typeface.createFromAsset(getContext().getAssets(),
"demofont.ttf");
setTypeface(tf);
}
}
Now, In your layout file you can use this like this way.
<YOUR_PACKAGE_NAME.DemoFont
android:layout_width="match_parent"
android:layout_height="wrap_content" />
First, you need to download a font file, which is usually of the .otf format. Then, you need to import this font into your assets folder in your android studio or eclipse project. After doing this you can create a new Typeface and set it to your text view. In terms of having different fonts for the hours and minutes digit, you need to create a layout with multiple text views. For example, you could do something like the following
<?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">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/hours_digit"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
android:id="#+id/time_colon"
android:layout_toEndOf="#id/hours_digit" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/time_colon"
android:id="#+id/minutes_digit"/>
</RelativeLayout>
Another way to accomplish this, rather than setting a typeface to a textview every single time, is to create your own custom textview, so that the typeface will be applied whenever you're using it. For example, for the minutes text view, you could do:
public class MinutesTextView extends TextView {
// Constructor method for the text view...
public MinutesTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
// Constructor method for the text view...
public MinutesTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
// Constructor method for the text view...
public MinutesTextView(Context context) {
super(context);
init(null);
}
// Initializes any UI properties of the text view.
private void init(AttributeSet attrs) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "Minutes-font-file.otf");
setTypeface(myTypeface);
}
}
and the, using the layout file from earlier.
<?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">
<com.example.yourpackage.MinutesTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/hours_digit"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=": "
android:id="#+id/time_colon"
android:layout_toEndOf="#id/hours_digit" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/time_colon"
android:id="#+id/minutes_digit"/>
</RelativeLayout>
First copy the fonts to the assets folder in your project.
For Hour Textview
public class HourTextView extends TextView {
public HourTextView(Context context) {
super(context);
init(null);
}
public HourTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
public HourTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
public HourTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
// Initializes any UI properties of the text view.
private void init(AttributeSet attrs) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "Hour-font-file.otf");
setTypeface(myTypeface);
}
}
For Minute Textview
public class MinuteTextView extends TextView {
public MinuteTextView(Context context) {
super(context);
init(null);
}
public MinuteTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
public MinuteTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
public MinuteTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
// Initializes any UI properties of the text view.
private void init(AttributeSet attrs) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "Minute-font-file.otf");
setTypeface(myTypeface);
}
}
For Seconds Textview
public class SecondTextView extends TextView {
public SecondTextView(Context context) {
super(context);
init(null);
}
public SecondTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(attrs);
}
public SecondTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
public SecondTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
// Initializes any UI properties of the text view.
private void init(AttributeSet attrs) {
Typeface myTypeface = Typeface.createFromAsset(getContext().getAssets(), "Second-font-file.otf");
setTypeface(myTypeface);
}
}
and in xml file do this,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.yourpackage.HourTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="10"
android:id="#+id/hourText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=" : " />
<com.yourpackage.MinuteTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="45 "
android:id="#+id/minuteText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text=" : " />
<com.yourpackage.SecondTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="28"
android:id="#+id/secondsText" />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
public TextView textView;
int countInt;
private int mInterval = 1000; // 1 second by default, can be changed later
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView=(TextView)findViewById(R.id.textView);
mHandler = new Handler();
startRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try {
countInt=countInt+1;
textView.setText(String.valueOf(countInt));
} finally {
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
}
I'm developing a music store where we show the albums in a grid. Each item is comprised of a cover album (which is a square image) and some text below it which shows artist name, album name, etc. This is the approximate result that I want:
Cover images are not uni-sized, some are 1000x1000, some are 500x500, and maybe there'll be some other sizes.
This is the current xml layout that I use for each item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/artistName"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Here is the important part of the RecyclerView's Adapter, the rest is typical stuff:
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.artistName.setText(mAlbums.get(position).name);
Picasso.with(holder.cover.getContext())
.load(mAlbums.get(position).primaryImage)
.into(holder.cover);
}
I get this result:
The right picture is 500x500 and the other two are 1000x1000
However if I add some resize to the images
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.artistName.setText(mAlbums.get(position).name);
Picasso.with(holder.cover.getContext())
.load(mAlbums.get(position).primaryImage)
.resize(300, 300)
.centerInside()
.into(holder.cover);
}
I'll get a better result like:
300 is just a random number. I can replace it with SCREEN_WIDTH/3.
So.... Is there a better approach to tackle this problem (which I think is a very general problem in apps)?
use the following SquareRelativeLayout
package net.simplyadvanced.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
/** A RelativeLayout that will always be square -- same width and height,
* where the height is based off the width. */
public class SquareRelativeLayout extends RelativeLayout {
public SquareRelativeLayout(Context context) {
super(context);
}
public SquareRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(VERSION_CODES.LOLLIPOP)
public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Set a square layout.
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
look at the answer
Recyclerview - GridLayoutManager: Set square dimensions
you can do like this. on your activity/fragment.
private void setRecyclerView() {
productRecyclerView.setHasFixedSize(true);
final GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 3);
productRecyclerView.setLayoutManager(layoutManager);
recyclerViewAdapter = new ProductListAdapter(getActivity());
productRecyclerView.setAdapter(recyclerViewAdapter);
}
or you can achieve by adding different viewholders of different row/column heights.
Use a fixed height for item xml Like
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="100dp">
<ImageView
android:id="#+id/cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="#+id/artistName"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Hope this will solve the problem