I created a custom SurfaceView called CaptureView and tried to add it into main.xml file:
<dev.recorder.client.CaptureView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="#+id/capturePreview"/>
The application seems to work fine but if I switch from main.xml tab to Layout in Eclipse the text NullPointerException appears instead of layout preview.
In the Activity I binded the controls the following way:
setContentView(R.layout.main);
bindControls();
private void bindControls()
{
videoPreview = (CaptureView)findViewById(R.id.capturePreview);
txtstatus = (TextView)findViewById(R.id.txtMode);
txtTimer = (TextView)findViewById(R.id.txtTime);
}
Does anyone know how this issue could be solved?
make sure that you are initializing the view in onFinishInflate and not in the constructor.
the layout preview code might initialize your control through a different code path.
Related
I am working on a React Native implementation of the Bitmovin player using their Android SDK. At this stage, I'm not sure how specific this is to the Bitmovin player, but as they don't officially support React Native at this stage, I want to ask about this on SO first. This is a React Native UI Component with a custom view, using a layout file. I am trying to present a subtitle view on top of a player view, and I have based my layout on Bitmovin's simple examples. In fact I have simplified the layout even further:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.bitmovin.player.PlayerView
android:id="#+id/bitmovinPlayerView"
app:shutter_background_color="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bootsplash_background">
<com.bitmovin.player.SubtitleView
android:id="#+id/bitmovinSubtitleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foregroundGravity="center" />
</com.bitmovin.player.PlayerView>
</LinearLayout>
This presents the SubtitleView at the top of the screen. Nothing I have tried so far presents the SubtitleView at the bottom of the screen in the more common position. I have experimented with every single parameter on all of these elements, as far as I can tell. Here is the code that initialises the view:
public void init() {
inflate(context, R.layout.player_container, this);
StyleConfig styleConfig = new StyleConfig();
styleConfig.setUiEnabled(false);
PlayerConfig playerConfig = new PlayerConfig();
playerConfig.setStyleConfig(styleConfig);
playerView = findViewById(R.id.bitmovinPlayerView);
player = Player.create(context, playerConfig);
playerView.setPlayer(player);
player.on(SourceEvent.Loaded.class, this::onLoad);
player.on(PlayerEvent.Playing.class, this::onPlay);
player.on(PlayerEvent.Paused.class, this::onPause);
player.on(PlayerEvent.Seek.class, this::onSeek);
player.on(PlayerEvent.TimeChanged.class, this::onTimeChanged);
player.on(PlayerEvent.Destroy.class, this::onDestroy);
player.on(PlayerEvent.Seeked.class, this::onSeeked);
player.on(PlayerEvent.PlaybackFinished.class, this::onPlaybackFinished);
player.on(PlayerEvent.Ready.class, this::onReady);
player.on(SourceEvent.Error.class, this::onError);
player.on(SourceEvent.SubtitleChanged.class, this::onSubtitleChanged);
player.on(PlayerEvent.Error.class, this::onError);
subtitleView = findViewById(R.id.bitmovinSubtitleView);
subtitleView.setPlayer(player);
player.setVolume(100);
}
I have read that React Native styles the top-level view of a UI Component, so this is my only clue at this stage. I'm unsure how to respond to that info however...
EDIT: The problem is likely to be that dynamically updating view layouts in Android in React Native is not straightforward. This has been discussed at length here.
EDIT 2: I have tried to listen for global layout changes, which is one of the proposed workarounds for view layout issues:
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
requestLayout();
}
});
This is called as expected, but has no effect on the subtitleView, which still displays at the top of the player, which seems to be because it has a height of 0.
EDIT 3: Another suggested solution that didn't work for me:
private void setupLayoutHack() {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
#Override
public void doFrame(long frameTimeNanos) {
manuallyLayoutChildren();
getViewTreeObserver().dispatchOnGlobalLayout();
Choreographer.getInstance().postFrameCallback(this);
}
});
}
private void manuallyLayoutChildren() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
}
I called setupLayoutHack() in the constructor but saw no difference after applying those changes either :(
EDIT 4: My final attempt at fixing the SubtitleView layout was experimenting with measuring and laying out in various ways:
private void refreshViewChildrenLayout(View view){
view.measure(
View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
However, the height in all cases that I tried was 0, which meant nothing was altered. There is a solution mentioned in the above RN issue that suggests that the shadow node for the subtitle view should be overridden. So one way forward could be to build a new subtitle view that has that included.
However, at this stage it seems to me an easier approach to respond to subtitle cues in React Native and perform all display and styling there.
(There is also a lesser issue of how to make the background on either side of the text transparent, but the layout issue is far more important at this stage).
Disclaimer: I'm not very familiar with React Native and how it influences layout creation if at all.
However looking at your layout file, it indicates that the SubtitleView is the top child of the PlayerView, which is a FrameLayout, thus gets added at the top (left). By specifying android:layout_height="wrap_content" on the SubtitleView it will only take up space that is required by the view. In the Bitmovin sample, it is generated in code and therefore should inherit the attributes from the parent, which is a RelativeLayout with android:layout_weight="1" which results in stretching it's height to the space available.
Long story short, try setting the height of your SubtitleView to match_parent
Just wondering if any of you guys could help me to access an element from an 'include' layout file which is inside not an activity but a fragment?
Most posts tell me to do something like that:
How to access Button inside "include" layout but as I am not on an activity the listener for the image won't work.
Ps: The listener works (opens the nav drawer) when I call an element which is not in the include file but on the fragment layout.
That's what I have inside the onCreateView method for my fragment:
View myLayout = view.findViewById(R.id.layout_top_bar);
image = (ImageView) myLayout.findViewById(R.id.image_left_top_bar);
image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mainActivity = (MainActivity)getActivity();
mainActivity.openMenuDrawer();
}
});
That's my include layout file:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_top_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<ImageView
android:id="#+id/image_left_top_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/hamburger_icon" />
And that's how I'm including it within the fragment layout file:
<include layout="#layout/top_bar" />
Thanks very much for any help on that! :)
You can access it directly with the root layout of your fragment like this.
image = view.findViewById(R.id.image_left_top_bar);
In case we are adding the layout dynamically by inflating it, we use the approach you mentioned above but that's not needed here.
Put a id to the Layout and later access to the elemento.
View myLayout = findViewById( R.id.layout );
View myView = myLayout.findViewById( R.id.item );
Change:
getLayoutPosition()
For
getAdapterPosition()
I have code like this:
FrameLayout containerFrame = (FrameLayout) onThisActivity.findViewById(viewIDtoShowIndicatorOn);
onThisActivity.getLayoutInflater().inflate(R.layout.su_activity_indicator, containerFrame);
Then I try to access a view inside the layout:su_activity_indicator I just added like this:
suAnimatedImage = (SUAnimatedImage) onThisActivity.findViewById(R.id.loadinganimationView);
suAnimatedImage.setImageDrawable(bt);
Does all this seem correct to all of you guys? I checked that it found everything and no nulls, but it never applies the image on screen.
Maybe you haven't set your inflated view to onThisActivity
onThisActivity = LayoutInflator.from(containerFrame.getContext()).inflate(R.layout.su_activity_indicator, containerFrame, false);
This question comes up quite often, however in all examples i have found, the image src is defined in the XML. e.g android:src="..."
My code doesn't specificy the src untill the activity, using ImageButton.setImageResource() as it is a single button, performing play/stop
How do i fill the ImageButton with the src, when src is defined later?
I tryed ImageButton.setScaleType="fitXY", however sdk doesn't like it using string...
UPDATE: After trying to use the suggested below, the problem still occurs. here is more explanation to help
<ImageButton
android:id="#+id/imgStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
/>
public class MainActivity extends Activity{
private ImageButton player;
protected void onCreate(){
player = (ImageButton) findViewById(R.id.imgStart);
...
if(isPlaying){
player.setImageResource(bitmap image);
}
else{
player.setImageResource(different bitmap image);
}
...
}
Use ScaleType.CENTER_CROP instead
player .setScaleType(ImageView.ScaleType.CENTER_CROP);
It seems CENTER_CROP works as fit_xy.
but, it's not sure why it does..
Please try below code to set ScaleType programatically
ImageButton object".setScaleType(ScaleType.FIT_XY)
"ImageButton object" should be object of class ImageButton
(that you defined probably in xml).
Do it this way
ImageButton object.setScaleType(ScaleType.FIT_XY)
Use ScaleType.FIT_XY instead of fitXY in your code
ImageButton.setScaleType="fitXY"
yes this will not work, because you have to use it properly using below code also should setAdjustViewBounds to true.like this:
player.setAdjustViewBounds(true);
player.setScaleType(ScaleType.FIT_XY);
This will definitely work!
What I would like to accomplish is to, at runtime, place a button in the middle of the screen, as the very top layer, overlaying anything below it. (It's not big, so it will not completely cover the screen, just whatever happens to be below it.)
I looked at creating a custom dialog, however that blocks all other user input. I want all of the views below this new button to act normally and respond to the user, but I just want to add (and later remove) the button above everything.
Hopefully that makes sense. I'm just wondering what might be the best approach to look into?
Use a FrameLayout, with the button as it's 2nd child. Set it to GONE when you don't want it visible.
I had to overlay a simple layout programmatically on top of any visible activity. Normal activity layout xmls don't know anything about the overlay. Layout had one textview component but could have any structure you see fit. This is my overlay layout.
res/layout/identity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/identitylayout"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<TextView
android:id="#+id/identityview"
android:padding="5dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#FFFFFF" android:background="#FF6600"
android:textSize="30dp"
/>
</RelativeLayout>
Overlay is shown on top of the existing content, after timeout is deleted from the screen. Application calls this function to display overlay.
private void showIdentity(String tag, long duration) {
// default text with ${xx} placeholder variables
String desc = getString(R.string.identity);
desc = desc.replace("${id}", reqId!=null ? reqId : "RequestId not found" );
desc = desc.replace("${tag}", tag!=null ? tag : "" );
desc = desc.trim();
// get parent and overlay layouts, use inflator to parse
// layout.xml to view component. Reuse existing instance if one is found.
ViewGroup parent = (ViewGroup)findViewById(R.id.mainlayout);
View identity = findViewById(R.id.identitylayout);
if (identity==null) {
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
identity = inflater.inflate(R.layout.identity, parent, false);
parent.addView(identity);
}
TextView text = (TextView)identity.findViewById(R.id.identityview);
text.setText(desc);
identity.bringToFront();
// use timer to hide after timeout, make sure there's only
// one instance in a message queue.
Runnable identityTask = new Runnable(){
#Override public void run() {
View identity = findViewById(R.id.identitylayout);
if (identity!=null)
((ViewGroup)identity.getParent()).removeView(identity);
}
};
messageHandler.removeCallbacksAndMessages("identitytask");
messageHandler.postAtTime(identityTask, "identitytask", SystemClock.uptimeMillis()+duration);
}
Timer messageHandler is member of main Activity instance (private Handler messageHandler) where I put all scheduled tasks. I am using Android 4.1 device lower than that I don't know what happens.