blob: edcf05987b3209bd5370a8947d81ef666df8c3d0 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.support.constraint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;
/**
* <b>Added in 1.1</b>
* <p>
* A {@code Placeholder} provides a virtual object which can position an existing object.
* <p>
* When the id of another view is set on a placeholder (using {@code setContent()}),
* the placeholder effectively becomes the content view. If the content view exist on the
* screen it is treated as gone from its original location.
* <p>
* The content view is positioned using the layout of the parameters of the {@code Placeholder} (the {@code Placeholder}
* is simply constrained in the layout like any other view).
* </p>
*
*/
public class Placeholder extends View {
private int mContentId = -1;
private View mContent = null;
private int mEmptyVisibility = View.INVISIBLE;
public Placeholder(Context context) {
super(context);
init(null);
}
public Placeholder(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public Placeholder(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
public Placeholder(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
super.setVisibility(mEmptyVisibility);
mContentId = -1;
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ConstraintLayout_placeholder);
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
if (attr == R.styleable.ConstraintLayout_placeholder_content) {
mContentId = a.getResourceId(attr, mContentId);
} else {
if (attr == R.styleable.ConstraintLayout_placeholder_emptyVisibility) {
mEmptyVisibility = a.getInt(attr, mEmptyVisibility);
}
}
}
}
}
/**
* Sets the visibility of placeholder when not containing objects typically gone or invisible.
* This can be important as it affects behaviour of surrounding components.
*
* @param visibility Either View.VISIBLE, View.INVISIBLE, View.GONE
*/
public void setEmptyVisibility(int visibility) {
mEmptyVisibility = visibility;
}
/**
* Returns the behaviour of a placeholder when it contains no view.
*
* @return Either View.VISIBLE, View.INVISIBLE, View.GONE. Default is INVISIBLE
*/
public int getEmptyVisibility() {
return mEmptyVisibility;
}
/**
* Returns the content view
* @return {@code null} if no content is set, otherwise the content view
*/
public View getContent() {
return mContent;
}
/**
* @hide
* @param canvas
*/
public void onDraw(Canvas canvas) {
if (isInEditMode()) {
canvas.drawRGB(223, 223, 223);
Paint paint = new Paint();
paint.setARGB(255, 210, 210, 210);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
Rect r = new Rect();
canvas.getClipBounds(r);
paint.setTextSize(r.height());
int cHeight = r.height();
int cWidth = r.width();
paint.setTextAlign(Paint.Align.LEFT);
String text = "?";
paint.getTextBounds(text, 0, text.length(), r);
float x = cWidth / 2f - r.width() / 2f - r.left;
float y = cHeight / 2f + r.height() / 2f - r.bottom;
canvas.drawText(text, x, y, paint);
}
}
/**
* @hide
* @param container
*/
public void updatePreLayout(ConstraintLayout container) {
if (mContentId == -1) {
if (!isInEditMode()) {
setVisibility(mEmptyVisibility);
}
}
mContent = container.findViewById(mContentId);
if (mContent != null) {
ConstraintLayout.LayoutParams layoutParamsContent = (ConstraintLayout.LayoutParams) mContent
.getLayoutParams();
layoutParamsContent.isInPlaceholder = true;
mContent.setVisibility(View.VISIBLE);
setVisibility(View.VISIBLE);
}
}
/**
* Sets the content view id
*
* @param id the id of the content view we want to place in the Placeholder
*/
public void setContentId(int id) {
if (mContentId == id) {
return;
}
if (mContent != null) {
mContent.setVisibility(VISIBLE); // ???
ConstraintLayout.LayoutParams layoutParamsContent = (ConstraintLayout.LayoutParams) mContent
.getLayoutParams();
layoutParamsContent.isInPlaceholder = false;
mContent = null;
}
mContentId = id;
if (id != ConstraintLayout.LayoutParams.UNSET) {
View v = ((View) getParent()).findViewById(id);
if (v != null) {
v.setVisibility(GONE);
}
}
}
/**
* @hide
* @param container
*/
public void updatePostMeasure(ConstraintLayout container) {
if (mContent == null) {
return;
}
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) getLayoutParams();
ConstraintLayout.LayoutParams layoutParamsContent = (ConstraintLayout.LayoutParams) mContent
.getLayoutParams();
layoutParamsContent.widget.setVisibility(View.VISIBLE);
layoutParams.widget.setWidth(layoutParamsContent.widget.getWidth());
layoutParams.widget.setHeight(layoutParamsContent.widget.getHeight());
layoutParamsContent.widget.setVisibility(View.GONE);
}
}