My .xml:
<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"
tools:context="com.example.eleizo.firstapplication.MainActivity"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:id="#+id/topRL">
</RelativeLayout>
....
I added my custom ImageView object in RelativeLayout topRL.addView(map); Constructor of the custom ImageView is:
public CustomImageView(Context context) {
super(context);
init();
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,1);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT,1);
setBackgroundColor(Color.BLUE);
this.setWillNotDraw(false);
setLayoutParams(params);
}
On create:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.example.eleizo.firstapplication.R.layout.activity_main);
RL = (RelativeLayout) findViewById(R.id.topRL);
Context context = getApplicationContext();
map = new CustomImageView(context);
RL.addView(map,map.params);
But RelativeLayout.ALIGN_PARENT_RIGHT,RelativeLayout.ALIGN_PARENT_BOTTOM doesn't work: After map.setImageBitmap(input); I see my image in left-top corner.
I want bottom-right corner of the image is on botton-right corner of the RelativeLayout independently of size of the image.
Where did I make the mistake?
You have your addRule wrong. Check this links:
a) https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html#addRule(int)
b) https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams.html#addRule(int, int)
If you want to pass multiple rules you have to call consecutively:
.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
If you want a subject that represents the value of the param to set you have to use the 2 parameters method addRule(int, int/bool).
Here is the solution which worked for me.
CustomeImageView.java
public class CustomImageView extends AppCompatImageView {
public CustomImageView(Context context) {
super(context);
init();
}
public CustomImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
setLayoutParams(params);
}
}
main_activity.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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.icpl.threadsample.MainActivity"
tools:showIn="#layout/activity_main">
<RelativeLayout
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/black"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
CustomImageView imageView = new CustomImageView(MainActivity.this);
imageView.setImageResource(R.mipmap.ic_launcher);
relativeLayout.addView(imageView);
}
});
}
}
Checkout this Answer as well.
Related
When I try to create my GameView, I get an error "function call expected".
in my Main activity:
GameView gv = GameView(this, null);
public class GameView extends View {
private Drawable mCustomImage;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
mCustomImage = context.getResources().getDrawable(R.drawable.bg);
}
protected void onDraw(Canvas canvas) {
Rect imageBounds = canvas.getClipBounds(); // Adjust this for where you want it
mCustomImage.setBounds(imageBounds);
mCustomImage.draw(canvas);
}
}
}
How do I create this dynamically?
I'm trying to add a view to my activity. The GameView will then control the position of its subviews programmatically.
This will make scene
I made some new changes in your GameView class. Below is copy of new GameView class.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
public class GameView extends View {
private Context mContext;
private Drawable mCustomImage;
public GameView(Context context) {
super(context);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
public GameView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
public GameView(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
public GameView(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
mCustomImage = ContextCompat.getDrawable(context, R.mipmap.ic_launcher);
}
#Override
protected void onDraw(Canvas canvas) {
Rect imageBounds = canvas.getClipBounds();
mCustomImage.setBounds(imageBounds);
mCustomImage.draw(canvas);
}
}
Adding it through xml inside activity.
<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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="#+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<GameView
android:layout_width="50dp"
android:layout_height="50dp" />
</LinearLayout>
</ScrollView>
Output
Adding it through code in activity
public class CustomActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw_line);
initialiseView();
}
private void initialiseView() {
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout);
GameView mGameView = new GameView(this);
mLinearLayout.addView(mGameView);
}
}
Output
EDIT
If you want to set parameters while adding it pragmatically then initialiseView method will be like
private void initialiseView() {
LinearLayout mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout);
GameView mGameView = new GameView(this);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(50, 50);
mGameView.setLayoutParams(layoutParams);
mLinearLayout.addView(mGameView);
}
Output :
GameView is a class, not a method, so you must call new to use them,
try this:
GameView gv = new GameView(this, null);
public class GameView extends View {
private Drawable mCustomImage;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
mCustomImage = context.getResources().getDrawable(R.drawable.bg);
}
....
Use new GameView(this, null); inside onCreate of your activity to create a new instance of your view.
Then use the method setContentView(View) to use it in your activity.
public class MainActivity extends AppCompatActivity{
private GameView gameView;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this, null);
setContentView(gameView);
//other code
}
//other methods
}
I created a custom view with the following code :
public class TestView extends LinearLayout {
public TestView(Context context) {
this(context, null);
}
public TestView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TestView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
LayoutInflater.from(context).inflate(R.layout.layout_test, this);
setBackgroundResource(R.color.black);
}
}
layout_test.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"/>
It works well, background is black.
But once I added background attribute to xml, setBackgroundResource
not work anymore(layout_test.xml):
<LinearLayout 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/white"/>
activity_layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<TestView
android:id="#+id/testView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
github.com/MummyDing/TestView
try this.
public class TestView extends LinearLayout {
public TestView(Context context) {
this(context, null);
setBackgroundResource(R.color.black);
}
public TestView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TestView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
LayoutInflater.from(context).inflate(R.layout.layout_test, this);
}
}
try to use with the help of context
LayoutInflater.from(context).inflate(R.layout.layout_test, this).
setBackgroundColor(context.getResources().getColor(R.color.colorAccent));
Try using an id like:
LinearLayout lLayout = (LinearLayout) findViewById(R.layout.my_linear_id);
lLayout.setBackgroundColor(context.getResources().getColor(R.color.green_color));
where my_linear_id is the id of you LinearLayout
I create an autoCompleteTextView as below Layout and Java class :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/autoCompleteTextViewGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:minHeight="#dimen/component_height">
<android.support.design.widget.TextInputLayout
android:id="#+id/textInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:animateLayoutChanges="true">
<AutoCompleteTextView
android:id="#+id/autoCompleteTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<android.support.v4.widget.ContentLoadingProgressBar
android:id="#+id/progressBar"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:indeterminate="true"
android:indeterminateDrawable="#anim/anim_indeterminate_mini"
android:interpolator="#anim/anim_progress_interpolator"
android:visibility="visible" />
</FrameLayout>
and Java class is :
public class MAutoCompleteText extends LinearLayout {
AutoCompleteTextView autoCompleteTextView;
ContentLoadingProgressBar progressBar;
TextInputLayout textInputLayout;
ViewGroup autoCompleteTextViewGroup;
public MAutoCompleteText(Context context) {
super(context);
init(context);
}
public MAutoCompleteText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MAutoCompleteText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
#TargetApi(21)
public MAutoCompleteText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
}
private void init(Context context) {
inflate(context, R.layout.layout_auto_complete_text, this);
autoCompleteTextViewGroup = (ViewGroup) findViewById(R.id.autoCompleteTextViewGroup);
textInputLayout = (TextInputLayout) findViewById(R.id.textInputLayout);
autoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView);
progressBar = (ContentLoadingProgressBar) findViewById(R.id.progressBar);
}
public void setAdapter(ArrayAdapter<String> adapter) {
autoCompleteTextView.setAdapter(adapter);
}
public String getText() {
return autoCompleteTextView.getText().toString();
}
public void setErrorEnabled(boolean status) {
textInputLayout.setErrorEnabled(status);
}
public void setError(int errorId) {
textInputLayout.setError(getContext().getString(errorId));
}
public int getVisibility() {
return autoCompleteTextViewGroup.getVisibility();
}
public void setVisibility(int visibility) {
autoCompleteTextViewGroup.setVisibility(visibility);
autoCompleteTextViewGroup.setMinimumHeight(R.dimen.component_height);
}
public void setProgressBarVisibility(int visibility) {
progressBar.setVisibility(visibility);
}
public MAutoCompleteText setHint(int hintId) {
autoCompleteTextView.setHint(hintId);
return this;
}
public void setImeOption(int imeOption) {
autoCompleteTextView.setImeOptions(imeOption);
}
}
Everything work OK. I setVisibility(GONE) and my component hide from UI,
but when I use setVisibility(VISIBLE) doesn't happen any thing !!!!
How can I display my component programmatically?
I found answer of my problem , at least it works now ... :)
I change setVisibility to below code :
public void setVisibility(int visibility) {
autoCompleteTextViewGroup.setVisibility(visibility);
if (visibility == View.VISIBLE) {
textInputLayout.setVisibility(visibility);
autoCompleteTextView.setVisibility(visibility);
progressBar.setVisibility(visibility);
requestLayout();
}
}
In fact requestLayout(); reDraw layout of my component on UI again and it`s appear correctly .
I have a custom CircleButton class:
public class CircleButton extends ImageView {
private int radius;
private int x;
private int y;
public CircleButton(Context context) {
super(context);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs) {
super(context, attrs);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
constructorTask();
}
public CircleButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
constructorTask();
}
private void constructorTask() {
x = 300;
y = 300;
radius = 100;
}
#Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
Log.i("Button Logger","Button Pressed");
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, radius, GameView.green);
Log.i("Drawing status", "CircleButton Drawing...");
}
}
I have a single activity. This activity contains a relative layout with a single custom view.
Here is the custom view:
public class GameView extends View {
public static Paint green = new Paint();
public GameView(Context context) {
super(context);
green.setARGB(255,0,255,0);
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
green.setARGB(255, 0, 255, 0);
}
public GameView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
green.setARGB(255, 0, 255, 0);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("GameView Draw Status","Drawing...");
Main.testButton.invalidate();
invalidate();
}
}
And here is the activity code:
public class Main extends AppCompatActivity {
public static CircleButton testButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testButton = new CircleButton(getApplicationContext());
makeFullScreen();
RelativeLayout screenLayout = (RelativeLayout) findViewById(R.id.screenLayout);
screenLayout.addView(testButton);
}
private void makeFullScreen() {...}
}
For some reason my testButton is not being drawn. Why is it not being drawn?
EDIT ONE: Here is the XML I have.
<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="0dp"
android:paddingLeft="0dp"
android:paddingRight="0dp"
android:paddingTop="0dp"
tools:context="com.example.vroy.customcirclebuttontest.Main"
android:id="#+id/screenLayout">
<com.example.vroy.customcirclebuttontest.GameView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:id="#+id/gameScreen" />
</RelativeLayout>
EDIT TWO: I did some further debugging by adding a normal button to the relative layout and it worked fine.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testCircleButton = new CircleButton(getApplicationContext());
makeFullScreen();
testButton = new Button(getApplicationContext());
testButton.setX(100);
testButton.setY(100);
testButton.setText("HELLO WORLD");
RelativeLayout screenLayout = (RelativeLayout) findViewById(R.id.screenLayout);
screenLayout.addView(testCircleButton);
screenLayout.addView(testButton);
Log.i("Button Status","Adding Button To Layout");
}
For some reason by circleButton is not working but a normal button is.
You are not specifying the size of the View (layout_width and layout_height), and thus your view is getting rendered inside a 0px by 0px space and thus invisible.
You can set those programatically using LayoutParams before adding your views to the layout.
For example with absolute size:
testButton.setLayoutParams(new ViewGroup.LayoutParams(100,100));
Although keep in mind the difference between px and dip. You would probably want to set the values using your internal radius attribute instead of harcoding them.
I am trying to build a custom view in Android that shows an image, and some text fields (non-editable).
I started by extending the RelativeLayout class for my custom view.
In the constructor of my custom view I created an ImageView and a TextView, and added them to the layout.
The TextView is loaded immediately, but the ImageView is loaded on a different thread and the bitmap is populated through a handler.
Once the bitmap is loaded, the ImageView is overlapping the TextView. The TextView is supposed to be on the "right-of" the ImageView, but this adjustment is not happening automatically.
I tried using customView.invalidate(), but that did not help.
This problem is not there when the same components are declared via XML.
Any help in resolving would be appreciated. Thanks
public class MyView extends RelativeLayout {
private TextView productName;
private ImageView productImage;
public MyView(Context context) {
super(context);
initHandler();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initHandler();
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initHandler();
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
initHandler();
}
private void initHandler() {
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
// implement logic to show content here
productName.setText(currentProduct.getTitle());
productImage.setImageBitmap(currentProduct.getImageBitmap());
MyView.this.invalidate();
}
};
productImage = new ImageView(getContext());
RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layout.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
layout.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
productImage.setLayoutParams(layout);
//keep the textview to right of imageview
productName = new TextView(getContext());
layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
layout.addRule(RelativeLayout.RIGHT_OF, productImage.getId());
layout.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
productName.setLayoutParams(layout);
productName.setTextColor(Color.parseColor("#ffffff"));
this.addView(productImage);
this.addView(productName);
//logic to load content on a new thread goes here
}
}
XML in which I included the custom view:
<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">
<com.mycompany.MyView
android:background="#android:color/black"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
you need add an id to your View in xml
<com.mycompany.MyView
android:id="#+id/myView"
android:background="#android:color/black"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
and in your java initilize it like
ImageView im = (ImageView)findViewById(R.id.myView);
try that